diff --git a/.style.yapf b/.style.yapf
deleted file mode 100644
index 0e9640c2..00000000
--- a/.style.yapf
+++ /dev/null
@@ -1,2 +0,0 @@
-[style]
-based_on_style = google
diff --git a/nonebot/__init__.py b/nonebot/__init__.py
index 809b696c..9d90ac19 100644
--- a/nonebot/__init__.py
+++ b/nonebot/__init__.py
@@ -40,8 +40,7 @@ from nonebot.log import logger, default_filter
from nonebot.drivers import Driver, ReverseDriver
try:
- _dist: pkg_resources.Distribution = pkg_resources.get_distribution(
- "nonebot2")
+ _dist: pkg_resources.Distribution = pkg_resources.get_distribution("nonebot2")
__version__ = _dist.version
VERSION = _dist.parsed_version
except pkg_resources.DistributionNotFound:
@@ -100,8 +99,8 @@ def get_app() -> Any:
"""
driver = get_driver()
assert isinstance(
- driver,
- ReverseDriver), "app object is only available for reverse driver"
+ driver, ReverseDriver
+ ), "app object is only available for reverse driver"
return driver.server_app
@@ -128,8 +127,8 @@ def get_asgi() -> Any:
"""
driver = get_driver()
assert isinstance(
- driver,
- ReverseDriver), "asgi object is only available for reverse driver"
+ driver, ReverseDriver
+ ), "asgi object is only available for reverse driver"
return driver.asgi
@@ -226,17 +225,23 @@ def init(*, _env_file: Optional[str] = None, **kwargs):
if not _driver:
logger.success("NoneBot is initializing...")
env = Env()
- config = Config(**kwargs,
- _common_config=env.dict(),
- _env_file=_env_file or f".env.{env.environment}")
+ config = Config(
+ **kwargs,
+ _common_config=env.dict(),
+ _env_file=_env_file or f".env.{env.environment}",
+ )
default_filter.level = (
- "DEBUG" if config.debug else
- "INFO") if config.log_level is None else config.log_level
+ ("DEBUG" if config.debug else "INFO")
+ if config.log_level is None
+ else config.log_level
+ )
logger.opt(colors=True).info(
- f"Current Env: {escape_tag(env.environment)}")
+ f"Current Env: {escape_tag(env.environment)}"
+ )
logger.opt(colors=True).debug(
- f"Loaded Config: {escape_tag(str(config.dict()))}")
+ f"Loaded Config: {escape_tag(str(config.dict()))}"
+ )
modulename, _, cls = config.driver.partition(":")
module = importlib.import_module(modulename)
@@ -247,10 +252,7 @@ def init(*, _env_file: Optional[str] = None, **kwargs):
_driver = DriverClass(env, config)
-def run(host: Optional[str] = None,
- port: Optional[int] = None,
- *args,
- **kwargs):
+def run(host: Optional[str] = None, port: Optional[int] = None, *args, **kwargs):
"""
:说明:
diff --git a/nonebot/adapters/__init__.py b/nonebot/adapters/__init__.py
index 74d26f69..a3080971 100644
--- a/nonebot/adapters/__init__.py
+++ b/nonebot/adapters/__init__.py
@@ -9,13 +9,13 @@ from typing import Iterable
try:
import pkg_resources
+
pkg_resources.declare_namespace(__name__)
del pkg_resources
except ImportError:
import pkgutil
- __path__: Iterable[str] = pkgutil.extend_path(
- __path__, # type: ignore
- __name__)
+
+ __path__: Iterable[str] = pkgutil.extend_path(__path__, __name__) # type: ignore
del pkgutil
except Exception:
pass
diff --git a/nonebot/adapters/_bot.py b/nonebot/adapters/_bot.py
index b96e31ae..6ed7b2b2 100644
--- a/nonebot/adapters/_bot.py
+++ b/nonebot/adapters/_bot.py
@@ -15,7 +15,6 @@ if TYPE_CHECKING:
class _ApiCall(Protocol):
-
async def __call__(self, **kwargs: Any) -> Any:
...
@@ -146,7 +145,8 @@ class Bot(abc.ABC):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running CallingAPI hook. "
- "Running cancelled!")
+ "Running cancelled!"
+ )
exception = None
result = None
@@ -157,8 +157,8 @@ class Bot(abc.ABC):
exception = e
coros = list(
- map(lambda x: x(self, exception, api, data, result),
- self._called_api_hook))
+ map(lambda x: x(self, exception, api, data, result), self._called_api_hook)
+ )
if coros:
try:
logger.debug("Running CalledAPI hooks...")
@@ -166,16 +166,17 @@ class Bot(abc.ABC):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running CalledAPI hook. "
- "Running cancelled!")
+ "Running cancelled!"
+ )
if exception:
raise exception
return result
@abc.abstractmethod
- async def send(self, event: "Event", message: Union[str, "Message",
- "MessageSegment"],
- **kwargs) -> Any:
+ async def send(
+ self, event: "Event", message: Union[str, "Message", "MessageSegment"], **kwargs
+ ) -> Any:
"""
:说明:
diff --git a/nonebot/adapters/_event.py b/nonebot/adapters/_event.py
index 669b4cf2..933a7085 100644
--- a/nonebot/adapters/_event.py
+++ b/nonebot/adapters/_event.py
@@ -2,9 +2,8 @@ import abc
from pydantic import BaseModel
-from nonebot.utils import DataclassEncoder
-
from ._message import Message
+from nonebot.utils import DataclassEncoder
class Event(abc.ABC, BaseModel):
diff --git a/nonebot/adapters/_message.py b/nonebot/adapters/_message.py
index b05a35a6..3175bed8 100644
--- a/nonebot/adapters/_message.py
+++ b/nonebot/adapters/_message.py
@@ -1,8 +1,17 @@
import abc
from copy import deepcopy
from dataclasses import field, asdict, dataclass
-from typing import (Any, Dict, List, Type, Union, Generic, Mapping, TypeVar,
- Iterable)
+from typing import (
+ Any,
+ Dict,
+ List,
+ Type,
+ Union,
+ Generic,
+ Mapping,
+ TypeVar,
+ Iterable,
+)
from ._template import MessageTemplate
@@ -14,6 +23,7 @@ TM = TypeVar("TM", bound="Message")
@dataclass
class MessageSegment(Mapping, abc.ABC, Generic[TM]):
"""消息段基类"""
+
type: str
"""
- 类型: ``str``
@@ -82,11 +92,12 @@ class MessageSegment(Mapping, abc.ABC, Generic[TM]):
class Message(List[TMS], abc.ABC):
"""消息数组"""
- def __init__(self: TM,
- message: Union[str, None, Mapping, Iterable[Mapping], TMS, TM,
- Any] = None,
- *args,
- **kwargs):
+ def __init__(
+ self: TM,
+ message: Union[str, None, Mapping, Iterable[Mapping], TMS, TM, Any] = None,
+ *args,
+ **kwargs,
+ ):
"""
:参数:
@@ -103,8 +114,7 @@ class Message(List[TMS], abc.ABC):
self.extend(self._construct(message))
@classmethod
- def template(cls: Type[TM],
- format_string: Union[str, TM]) -> MessageTemplate[TM]:
+ def template(cls: Type[TM], format_string: Union[str, TM]) -> MessageTemplate[TM]:
"""
:说明:
@@ -156,8 +166,7 @@ class Message(List[TMS], abc.ABC):
@staticmethod
@abc.abstractmethod
- def _construct(
- msg: Union[str, Mapping, Iterable[Mapping], Any]) -> Iterable[TMS]:
+ def _construct(msg: Union[str, Mapping, Iterable[Mapping], Any]) -> Iterable[TMS]:
raise NotImplementedError
def __add__(self: TM, other: Union[str, Mapping, Iterable[Mapping]]) -> TM:
diff --git a/nonebot/adapters/_template.py b/nonebot/adapters/_template.py
index 94472018..fad17d84 100644
--- a/nonebot/adapters/_template.py
+++ b/nonebot/adapters/_template.py
@@ -1,8 +1,21 @@
import inspect
import functools
from string import Formatter
-from typing import (TYPE_CHECKING, Any, Set, List, Type, Tuple, Union, Generic,
- Mapping, TypeVar, Sequence, cast, overload)
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Set,
+ List,
+ Type,
+ Tuple,
+ Union,
+ Generic,
+ Mapping,
+ TypeVar,
+ Sequence,
+ cast,
+ overload,
+)
if TYPE_CHECKING:
from . import Message, MessageSegment
@@ -15,14 +28,15 @@ class MessageTemplate(Formatter, Generic[TF]):
"""消息模板格式化实现类"""
@overload
- def __init__(self: "MessageTemplate[str]",
- template: str,
- factory: Type[str] = str) -> None:
+ def __init__(
+ self: "MessageTemplate[str]", template: str, factory: Type[str] = str
+ ) -> None:
...
@overload
- def __init__(self: "MessageTemplate[TM]", template: Union[str, TM],
- factory: Type[TM]) -> None:
+ def __init__(
+ self: "MessageTemplate[TM]", template: Union[str, TM], factory: Type[TM]
+ ) -> None:
...
def __init__(self, template, factory=str) -> None:
@@ -51,15 +65,15 @@ class MessageTemplate(Formatter, Generic[TF]):
elif isinstance(self.template, self.factory):
template = cast("Message[MessageSegment]", self.template)
for seg in template:
- msg += self.vformat(str(seg), args,
- kwargs) if seg.is_text() else seg
+ msg += self.vformat(str(seg), args, kwargs) if seg.is_text() else seg
else:
- raise TypeError('template must be a string or instance of Message!')
+ raise TypeError("template must be a string or instance of Message!")
return msg
- def vformat(self, format_string: str, args: Sequence[Any],
- kwargs: Mapping[str, Any]) -> TF:
+ def vformat(
+ self, format_string: str, args: Sequence[Any], kwargs: Mapping[str, Any]
+ ) -> TF:
used_args = set()
result, _ = self._vformat(format_string, args, kwargs, used_args, 2)
self.check_unused_args(list(used_args), args, kwargs)
@@ -79,8 +93,9 @@ class MessageTemplate(Formatter, Generic[TF]):
results: List[Any] = []
- for (literal_text, field_name, format_spec,
- conversion) in self.parse(format_string):
+ for (literal_text, field_name, format_spec, conversion) in self.parse(
+ format_string
+ ):
# output the literal text
if literal_text:
@@ -96,14 +111,16 @@ class MessageTemplate(Formatter, Generic[TF]):
if auto_arg_index is False:
raise ValueError(
"cannot switch from manual field specification to "
- "automatic field numbering")
+ "automatic field numbering"
+ )
field_name = str(auto_arg_index)
auto_arg_index += 1
elif field_name.isdigit():
if auto_arg_index:
raise ValueError(
"cannot switch from manual field specification to "
- "automatic field numbering")
+ "automatic field numbering"
+ )
# disable auto arg incrementing, if it gets
# used later on, then an exception will be raised
auto_arg_index = False
@@ -132,8 +149,10 @@ class MessageTemplate(Formatter, Generic[TF]):
formatted_text = self.format_field(obj, str(format_control))
results.append(formatted_text)
- return self.factory(functools.reduce(self._add, results or
- [""])), auto_arg_index
+ return (
+ self.factory(functools.reduce(self._add, results or [""])),
+ auto_arg_index,
+ )
def format_field(self, value: Any, format_spec: str) -> Any:
if issubclass(self.factory, str):
@@ -142,11 +161,20 @@ class MessageTemplate(Formatter, Generic[TF]):
segment_class: Type[MessageSegment] = self.factory.get_segment_class()
method = getattr(segment_class, format_spec, None)
method_type = inspect.getattr_static(segment_class, format_spec, None)
- return (super().format_field(value, format_spec) if
- ((method is None) or
- (not isinstance(method_type, (classmethod, staticmethod))
- ) # Only Call staticmethod or classmethod
- ) else method(value)) if format_spec else value
+ return (
+ (
+ super().format_field(value, format_spec)
+ if (
+ (method is None)
+ or (
+ not isinstance(method_type, (classmethod, staticmethod))
+ ) # Only Call staticmethod or classmethod
+ )
+ else method(value)
+ )
+ if format_spec
+ else value
+ )
def _add(self, a: Any, b: Any) -> Any:
try:
diff --git a/nonebot/config.py b/nonebot/config.py
index 82fca0d3..4bbbf1f9 100644
--- a/nonebot/config.py
+++ b/nonebot/config.py
@@ -20,13 +20,17 @@ from ipaddress import IPv4Address
from typing import Any, Set, Dict, Tuple, Union, Mapping, Optional
from pydantic import BaseSettings, IPvAnyAddress
-from pydantic.env_settings import (SettingsError, EnvSettingsSource,
- InitSettingsSource, SettingsSourceCallable,
- read_env_file, env_file_sentinel)
+from pydantic.env_settings import (
+ SettingsError,
+ EnvSettingsSource,
+ InitSettingsSource,
+ SettingsSourceCallable,
+ read_env_file,
+ env_file_sentinel,
+)
class CustomEnvSettings(EnvSettingsSource):
-
def __call__(self, settings: BaseSettings) -> Dict[str, Any]:
"""
Build environment variables suitable for passing to the Model.
@@ -39,15 +43,24 @@ class CustomEnvSettings(EnvSettingsSource):
env_vars = {k.lower(): v for k, v in os.environ.items()}
env_file_vars: Dict[str, Optional[str]] = {}
- 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
+ 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(
env_path,
encoding=env_file_encoding,
- case_sensitive=settings.__config__.case_sensitive)
+ case_sensitive=settings.__config__.case_sensitive,
+ )
env_vars = {**env_file_vars, **env_vars}
for field in settings.__fields__.values():
@@ -66,14 +79,12 @@ class CustomEnvSettings(EnvSettingsSource):
try:
env_val = settings.__config__.json_loads(env_val)
except ValueError as e:
- raise SettingsError(
- f'error parsing JSON for "{env_name}"') from 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:
+ if (env_val is None or len(env_val) == 0) and env_name in env_vars:
env_val = env_vars[env_name]
try:
if env_val:
@@ -87,12 +98,10 @@ class CustomEnvSettings(EnvSettingsSource):
class BaseConfig(BaseSettings):
-
def __getattr__(self, name: str) -> Any:
return self.__dict__.get(name)
class Config:
-
@classmethod
def customise_sources(
cls,
@@ -101,10 +110,14 @@ class BaseConfig(BaseSettings):
file_secret_settings: SettingsSourceCallable,
) -> Tuple[SettingsSourceCallable, ...]:
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)
+ return (
+ init_settings,
+ CustomEnvSettings(
+ env_settings.env_file, env_settings.env_file_encoding
+ ),
+ InitSettingsSource(common_config),
+ file_secret_settings,
+ )
class Env(BaseConfig):
@@ -135,6 +148,7 @@ class Config(BaseConfig):
除了 NoneBot 的配置项外,还可以自行添加配置项到 ``.env.{environment}`` 文件中。
这些配置将会在 json 反序列化后一起带入 ``Config`` 类中。
"""
+
# nonebot configs
driver: str = "nonebot.drivers.fastapi"
"""
@@ -210,7 +224,7 @@ class Config(BaseConfig):
API_ROOT={"123456": "http://127.0.0.1:5700"}
"""
- api_timeout: Optional[float] = 30.
+ api_timeout: Optional[float] = 30.0
"""
- **类型**: ``Optional[float]``
- **默认值**: ``30.``
diff --git a/nonebot/dependencies/__init__.py b/nonebot/dependencies/__init__.py
index 44f568f7..c32a9ffe 100644
--- a/nonebot/dependencies/__init__.py
+++ b/nonebot/dependencies/__init__.py
@@ -21,9 +21,14 @@ from .models import Dependent as Dependent
from nonebot.exception import SkippedException
from .models import DependsWrapper as DependsWrapper
from nonebot.typing import T_Handler, T_DependencyCache
-from nonebot.utils import (CacheLock, run_sync, is_gen_callable,
- run_sync_ctx_manager, is_async_gen_callable,
- is_coroutine_callable)
+from nonebot.utils import (
+ CacheLock,
+ run_sync,
+ is_gen_callable,
+ run_sync_ctx_manager,
+ is_async_gen_callable,
+ is_coroutine_callable,
+)
cache_lock = CacheLock()
@@ -33,60 +38,59 @@ class CustomConfig(BaseConfig):
def get_param_sub_dependent(
- *,
- param: inspect.Parameter,
- allow_types: Optional[List[Type[Param]]] = None) -> Dependent:
+ *, param: inspect.Parameter, allow_types: Optional[List[Type[Param]]] = None
+) -> Dependent:
depends: DependsWrapper = param.default
if depends.dependency:
dependency = depends.dependency
else:
dependency = param.annotation
- return get_sub_dependant(depends=depends,
- dependency=dependency,
- name=param.name,
- allow_types=allow_types)
+ return get_sub_dependant(
+ depends=depends, dependency=dependency, name=param.name, allow_types=allow_types
+ )
def get_parameterless_sub_dependant(
- *,
- depends: DependsWrapper,
- allow_types: Optional[List[Type[Param]]] = None) -> Dependent:
+ *, depends: DependsWrapper, allow_types: Optional[List[Type[Param]]] = None
+) -> Dependent:
assert callable(
depends.dependency
), "A parameter-less dependency must have a callable dependency"
- return get_sub_dependant(depends=depends,
- dependency=depends.dependency,
- allow_types=allow_types)
+ return get_sub_dependant(
+ depends=depends, dependency=depends.dependency, allow_types=allow_types
+ )
def get_sub_dependant(
- *,
- depends: DependsWrapper,
- dependency: T_Handler,
- name: Optional[str] = None,
- allow_types: Optional[List[Type[Param]]] = None) -> Dependent:
- sub_dependant = get_dependent(func=dependency,
- name=name,
- use_cache=depends.use_cache,
- allow_types=allow_types)
+ *,
+ depends: DependsWrapper,
+ dependency: T_Handler,
+ name: Optional[str] = None,
+ allow_types: Optional[List[Type[Param]]] = None,
+) -> Dependent:
+ sub_dependant = get_dependent(
+ func=dependency, name=name, use_cache=depends.use_cache, allow_types=allow_types
+ )
return sub_dependant
-def get_dependent(*,
- func: T_Handler,
- name: Optional[str] = None,
- use_cache: bool = True,
- allow_types: Optional[List[Type[Param]]] = None) -> Dependent:
+def get_dependent(
+ *,
+ func: T_Handler,
+ name: Optional[str] = None,
+ use_cache: bool = True,
+ allow_types: Optional[List[Type[Param]]] = None,
+) -> Dependent:
signature = get_typed_signature(func)
params = signature.parameters
- dependent = Dependent(func=func,
- name=name,
- allow_types=allow_types,
- use_cache=use_cache)
+ dependent = Dependent(
+ func=func, name=name, allow_types=allow_types, use_cache=use_cache
+ )
for param_name, param in params.items():
if isinstance(param.default, DependsWrapper):
- sub_dependent = get_param_sub_dependent(param=param,
- allow_types=allow_types)
+ sub_dependent = get_param_sub_dependent(
+ param=param, allow_types=allow_types
+ )
dependent.dependencies.append(sub_dependent)
continue
@@ -111,44 +115,44 @@ def get_dependent(*,
required = default_value == Required
if param.annotation != param.empty:
annotation = param.annotation
- annotation = get_annotation_from_field_info(annotation, field_info,
- param_name)
+ annotation = get_annotation_from_field_info(annotation, field_info, param_name)
dependent.params.append(
- ModelField(name=param_name,
- type_=annotation,
- class_validators=None,
- model_config=CustomConfig,
- default=None if required else default_value,
- required=required,
- field_info=field_info))
+ ModelField(
+ name=param_name,
+ type_=annotation,
+ class_validators=None,
+ model_config=CustomConfig,
+ default=None if required else default_value,
+ required=required,
+ field_info=field_info,
+ )
+ )
return dependent
async def solve_dependencies(
- *,
- _dependent: Dependent,
- _stack: Optional[AsyncExitStack] = None,
- _sub_dependents: Optional[List[Dependent]] = None,
- _dependency_cache: Optional[T_DependencyCache] = None,
- **params: Any) -> Tuple[Dict[str, Any], T_DependencyCache]:
+ *,
+ _dependent: Dependent,
+ _stack: Optional[AsyncExitStack] = None,
+ _sub_dependents: Optional[List[Dependent]] = None,
+ _dependency_cache: Optional[T_DependencyCache] = None,
+ **params: Any,
+) -> Tuple[Dict[str, Any], T_DependencyCache]:
values: Dict[str, Any] = {}
dependency_cache = {} if _dependency_cache is None else _dependency_cache
# solve sub dependencies
sub_dependent: Dependent
- for sub_dependent in chain(_sub_dependents or tuple(),
- _dependent.dependencies):
+ for sub_dependent in chain(_sub_dependents or tuple(), _dependent.dependencies):
sub_dependent.func = cast(Callable[..., Any], sub_dependent.func)
- sub_dependent.cache_key = cast(Callable[..., Any],
- sub_dependent.cache_key)
+ sub_dependent.cache_key = cast(Callable[..., Any], sub_dependent.cache_key)
func = sub_dependent.func
# solve sub dependency with current cache
solved_result = await solve_dependencies(
- _dependent=sub_dependent,
- _dependency_cache=dependency_cache,
- **params)
+ _dependent=sub_dependent, _dependency_cache=dependency_cache, **params
+ )
sub_values, sub_dependency_cache = solved_result
# update cache?
# dependency_cache.update(sub_dependency_cache)
@@ -162,8 +166,7 @@ async def solve_dependencies(
_stack, AsyncExitStack
), "Generator dependency should be called in context"
if is_gen_callable(func):
- cm = run_sync_ctx_manager(
- contextmanager(func)(**sub_values))
+ cm = run_sync_ctx_manager(contextmanager(func)(**sub_values))
else:
cm = asynccontextmanager(func)(**sub_values)
solved = await _stack.enter_async_context(cm)
@@ -182,19 +185,17 @@ async def solve_dependencies(
# usual dependency
for field in _dependent.params:
field_info = field.field_info
- assert isinstance(field_info,
- Param), "Params must be subclasses of Param"
+ assert isinstance(field_info, Param), "Params must be subclasses of Param"
value = field_info._solve(**params)
if value == Undefined:
value = field.get_default()
- _, errs_ = field.validate(value,
- values,
- loc=(str(field_info), field.alias))
+ _, errs_ = field.validate(value, values, loc=(str(field_info), field.alias))
if errs_:
logger.debug(
f"{field_info} "
f"type {type(value)} not match depends {_dependent.func} "
- f"annotation {field._type_display()}, ignored")
+ f"annotation {field._type_display()}, ignored"
+ )
raise SkippedException
else:
values[field.name] = value
@@ -202,9 +203,7 @@ async def solve_dependencies(
return values, dependency_cache
-def Depends(dependency: Optional[T_Handler] = None,
- *,
- use_cache: bool = True) -> Any:
+def Depends(dependency: Optional[T_Handler] = None, *, use_cache: bool = True) -> Any:
"""
:说明:
diff --git a/nonebot/dependencies/models.py b/nonebot/dependencies/models.py
index 9acba4db..3fdb8e81 100644
--- a/nonebot/dependencies/models.py
+++ b/nonebot/dependencies/models.py
@@ -9,7 +9,6 @@ from nonebot.typing import T_Handler
class Param(abc.ABC, FieldInfo):
-
@classmethod
@abc.abstractmethod
def _check(cls, name: str, param: inspect.Parameter) -> bool:
@@ -21,11 +20,9 @@ class Param(abc.ABC, FieldInfo):
class DependsWrapper:
-
- def __init__(self,
- dependency: Optional[T_Handler] = None,
- *,
- use_cache: bool = True) -> None:
+ def __init__(
+ self, dependency: Optional[T_Handler] = None, *, use_cache: bool = True
+ ) -> None:
self.dependency = dependency
self.use_cache = use_cache
@@ -36,15 +33,16 @@ class DependsWrapper:
class Dependent:
-
- def __init__(self,
- *,
- func: Optional[T_Handler] = None,
- name: Optional[str] = None,
- params: Optional[List[ModelField]] = None,
- allow_types: Optional[List[Type[Param]]] = None,
- dependencies: Optional[List["Dependent"]] = None,
- use_cache: bool = True) -> None:
+ def __init__(
+ self,
+ *,
+ func: Optional[T_Handler] = None,
+ name: Optional[str] = None,
+ params: Optional[List[ModelField]] = None,
+ allow_types: Optional[List[Type[Param]]] = None,
+ dependencies: Optional[List["Dependent"]] = None,
+ use_cache: bool = True,
+ ) -> None:
self.func = func
self.name = name
self.params = params or []
diff --git a/nonebot/dependencies/utils.py b/nonebot/dependencies/utils.py
index ade7fd97..44a6b4c9 100644
--- a/nonebot/dependencies/utils.py
+++ b/nonebot/dependencies/utils.py
@@ -16,14 +16,14 @@ def get_typed_signature(func: T_Handler) -> inspect.Signature:
kind=param.kind,
default=param.default,
annotation=get_typed_annotation(param, globalns),
- ) for param in signature.parameters.values()
+ )
+ for param in signature.parameters.values()
]
typed_signature = inspect.Signature(typed_params)
return typed_signature
-def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str,
- Any]) -> Any:
+def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str, Any]) -> Any:
annotation = param.annotation
if isinstance(annotation, str):
annotation = ForwardRef(annotation)
@@ -31,7 +31,7 @@ def get_typed_annotation(param: inspect.Parameter, globalns: Dict[str,
annotation = evaluate_forwardref(annotation, globalns, globalns)
except Exception as e:
logger.opt(colors=True, exception=e).warning(
- f"Unknown ForwardRef[\"{param.annotation}\"] for parameter {param.name}"
+ f'Unknown ForwardRef["{param.annotation}"] for parameter {param.name}'
)
return inspect.Parameter.empty
return annotation
diff --git a/nonebot/drivers/__init__.py b/nonebot/drivers/__init__.py
index d08f6b0c..4add8a19 100644
--- a/nonebot/drivers/__init__.py
+++ b/nonebot/drivers/__init__.py
@@ -8,8 +8,17 @@
import abc
import asyncio
from dataclasses import field, dataclass
-from typing import (TYPE_CHECKING, Any, Set, Dict, Type, Union, Callable,
- Optional, Awaitable)
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Set,
+ Dict,
+ Type,
+ Union,
+ Callable,
+ Optional,
+ Awaitable,
+)
from nonebot.log import logger
from nonebot.utils import escape_tag
@@ -90,12 +99,14 @@ class Driver(abc.ABC):
"""
if name in self._adapters:
logger.opt(colors=True).debug(
- f'Adapter "{escape_tag(name)}" already exists')
+ f'Adapter "{escape_tag(name)}" already exists'
+ )
return
self._adapters[name] = adapter
adapter.register(self, self.config, **kwargs)
logger.opt(colors=True).debug(
- f'Succeeded to load adapter "{escape_tag(name)}"')
+ f'Succeeded to load adapter "{escape_tag(name)}"'
+ )
@property
@abc.abstractmethod
@@ -121,7 +132,8 @@ class Driver(abc.ABC):
* ``**kwargs``
"""
logger.opt(colors=True).debug(
- f"Loaded adapters: {escape_tag(', '.join(self._adapters))}")
+ f"Loaded adapters: {escape_tag(', '.join(self._adapters))}"
+ )
@abc.abstractmethod
def on_startup(self, func: Callable) -> Callable:
@@ -146,8 +158,7 @@ class Driver(abc.ABC):
self._bot_connection_hook.add(func)
return func
- def on_bot_disconnect(
- self, func: T_BotDisconnectionHook) -> T_BotDisconnectionHook:
+ def on_bot_disconnect(self, func: T_BotDisconnectionHook) -> T_BotDisconnectionHook:
"""
:说明:
@@ -172,7 +183,8 @@ class Driver(abc.ABC):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running WebSocketConnection hook. "
- "Running cancelled!")
+ "Running cancelled!"
+ )
asyncio.create_task(_run_hook(bot))
@@ -189,7 +201,8 @@ class Driver(abc.ABC):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running WebSocketDisConnection hook. "
- "Running cancelled!")
+ "Running cancelled!"
+ )
asyncio.create_task(_run_hook(bot))
@@ -201,8 +214,8 @@ class ForwardDriver(Driver):
@abc.abstractmethod
def setup_http_polling(
- self, setup: Union["HTTPPollingSetup",
- Callable[[], Awaitable["HTTPPollingSetup"]]]
+ self,
+ setup: Union["HTTPPollingSetup", Callable[[], Awaitable["HTTPPollingSetup"]]],
) -> None:
"""
:说明:
@@ -217,8 +230,7 @@ class ForwardDriver(Driver):
@abc.abstractmethod
def setup_websocket(
- self, setup: Union["WebSocketSetup",
- Callable[[], Awaitable["WebSocketSetup"]]]
+ self, setup: Union["WebSocketSetup", Callable[[], Awaitable["WebSocketSetup"]]]
) -> None:
"""
:说明:
@@ -288,6 +300,7 @@ class HTTPRequest(HTTPConnection):
.. _asgi http scope:
https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope
"""
+
method: str = "GET"
"""The HTTP method name, uppercased."""
body: bytes = b""
@@ -309,6 +322,7 @@ class HTTPResponse:
.. _asgi http scope:
https://asgi.readthedocs.io/en/latest/specs/www.html#http-connection-scope
"""
+
status: int
"""HTTP status code."""
body: Optional[bytes] = None
@@ -416,5 +430,5 @@ class WebSocketSetup:
"""URL"""
headers: Dict[str, str] = field(default_factory=dict)
"""HTTP headers"""
- reconnect_interval: float = 3.
+ reconnect_interval: float = 3.0
"""WebSocket 重连间隔"""
diff --git a/nonebot/drivers/aiohttp.py b/nonebot/drivers/aiohttp.py
index 3670c414..40879d62 100644
--- a/nonebot/drivers/aiohttp.py
+++ b/nonebot/drivers/aiohttp.py
@@ -20,13 +20,16 @@ from nonebot.typing import overrides
from nonebot.utils import escape_tag
from nonebot.config import Env, Config
from nonebot.drivers import WebSocket as BaseWebSocket
-from nonebot.drivers import (HTTPRequest, ForwardDriver, WebSocketSetup,
- HTTPPollingSetup)
+from nonebot.drivers import (
+ HTTPRequest,
+ ForwardDriver,
+ WebSocketSetup,
+ HTTPPollingSetup,
+)
STARTUP_FUNC = Callable[[], Awaitable[None]]
SHUTDOWN_FUNC = Callable[[], Awaitable[None]]
-HTTPPOLLING_SETUP = Union[HTTPPollingSetup,
- Callable[[], Awaitable[HTTPPollingSetup]]]
+HTTPPOLLING_SETUP = Union[HTTPPollingSetup, Callable[[], Awaitable[HTTPPollingSetup]]]
WEBSOCKET_SETUP = Union[WebSocketSetup, Callable[[], Awaitable[WebSocketSetup]]]
HANDLED_SIGNALS = (
signal.SIGINT, # Unix signal 2. Sent by Ctrl+C.
@@ -146,7 +149,8 @@ class Driver(ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running startup function. "
- "Ignored!")
+ "Ignored!"
+ )
async def main_loop(self):
await self.should_exit.wait()
@@ -160,24 +164,20 @@ class Driver(ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running shutdown function. "
- "Ignored!")
+ "Ignored!"
+ )
for task in self.connections:
if not task.done():
task.cancel()
await asyncio.sleep(0.1)
- tasks = [
- t for t in asyncio.all_tasks() if t is not asyncio.current_task()
- ]
+ tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
if tasks and not self.force_exit:
logger.info("Waiting for tasks to finish. (CTRL+C to force quit)")
while tasks and not self.force_exit:
await asyncio.sleep(0.1)
- tasks = [
- t for t in asyncio.all_tasks()
- if t is not asyncio.current_task()
- ]
+ tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
for task in tasks:
task.cancel()
@@ -209,9 +209,7 @@ class Driver(ForwardDriver):
self.should_exit.set()
async def _http_loop(self, setup: HTTPPOLLING_SETUP):
-
- async def _build_request(
- setup: HTTPPollingSetup) -> Optional[HTTPRequest]:
+ async def _build_request(setup: HTTPPollingSetup) -> Optional[HTTPRequest]:
url = URL(setup.url)
if not url.is_absolute() or not url.host:
logger.opt(colors=True).error(
@@ -219,10 +217,15 @@ class Driver(ForwardDriver):
)
return
host = f"{url.host}:{url.port}" if url.port else url.host
- return HTTPRequest(setup.http_version, url.scheme, url.path,
- url.raw_query_string.encode("latin-1"), {
- **setup.headers, "host": host
- }, setup.method, setup.body)
+ return HTTPRequest(
+ setup.http_version,
+ url.scheme,
+ url.path,
+ url.raw_query_string.encode("latin-1"),
+ {**setup.headers, "host": host},
+ setup.method,
+ setup.body,
+ )
bot: Optional[Bot] = None
request: Optional[HTTPRequest] = None
@@ -230,7 +233,8 @@ class Driver(ForwardDriver):
logger.opt(colors=True).info(
f"Start http polling for {escape_tag(setup.adapter.upper())} "
- f"Bot {escape_tag(setup.self_id)}")
+ f"Bot {escape_tag(setup.self_id)}"
+ )
try:
async with aiohttp.ClientSession() as session:
@@ -244,7 +248,8 @@ class Driver(ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error while parsing setup "
- f"{escape_tag(repr(setup))}.")
+ f"{escape_tag(repr(setup))}."
+ )
await asyncio.sleep(3)
continue
@@ -286,19 +291,22 @@ class Driver(ForwardDriver):
)
try:
- async with session.request(request.method,
- setup_.url,
- data=request.body,
- headers=headers,
- timeout=timeout,
- version=version) as response:
+ async with session.request(
+ request.method,
+ setup_.url,
+ data=request.body,
+ headers=headers,
+ timeout=timeout,
+ version=version,
+ ) as response:
response.raise_for_status()
data = await response.read()
asyncio.create_task(bot.handle_message(data))
except aiohttp.ClientResponseError as e:
logger.opt(colors=True, exception=e).error(
f"Error occurred while requesting {escape_tag(setup_.url)}. "
- "Try to reconnect...")
+ "Try to reconnect..."
+ )
await asyncio.sleep(setup_.poll_interval)
@@ -307,7 +315,8 @@ class Driver(ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Unexpected exception occurred "
- "while http polling")
+ "while http polling"
+ )
finally:
if bot:
self._bot_disconnect(bot)
@@ -327,7 +336,8 @@ class Driver(ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error while parsing setup "
- f"{escape_tag(repr(setup))}.")
+ f"{escape_tag(repr(setup))}."
+ )
await asyncio.sleep(3)
continue
@@ -346,17 +356,21 @@ class Driver(ForwardDriver):
f"Bot {setup_.self_id} from adapter {setup_.adapter} connecting to {url}"
)
try:
- async with session.ws_connect(url,
- headers=headers,
- timeout=30.) as ws:
+ async with session.ws_connect(
+ url, headers=headers, timeout=30.0
+ ) as ws:
logger.opt(colors=True).info(
f"WebSocket Connection to {escape_tag(setup_.adapter.upper())} "
f"Bot {escape_tag(setup_.self_id)} succeeded!"
)
request = WebSocket(
- "1.1", url.scheme, url.path,
- url.raw_query_string.encode("latin-1"), headers,
- ws)
+ "1.1",
+ url.scheme,
+ url.path,
+ url.raw_query_string.encode("latin-1"),
+ headers,
+ ws,
+ )
BotClass = self._adapters[setup_.adapter]
bot = BotClass(setup_.self_id, request)
@@ -365,25 +379,30 @@ class Driver(ForwardDriver):
msg = await ws.receive()
if msg.type == aiohttp.WSMsgType.text:
asyncio.create_task(
- bot.handle_message(msg.data.encode()))
+ bot.handle_message(msg.data.encode())
+ )
elif msg.type == aiohttp.WSMsgType.binary:
- asyncio.create_task(
- bot.handle_message(msg.data))
+ asyncio.create_task(bot.handle_message(msg.data))
elif msg.type == aiohttp.WSMsgType.error:
logger.opt(colors=True).error(
"Error while handling websocket frame. "
- "Try to reconnect...")
+ "Try to reconnect..."
+ )
break
else:
logger.opt(colors=True).error(
"WebSocket connection closed by peer. "
- "Try to reconnect...")
+ "Try to reconnect..."
+ )
break
- except (aiohttp.ClientResponseError,
- aiohttp.ClientConnectionError) as e:
+ except (
+ aiohttp.ClientResponseError,
+ aiohttp.ClientConnectionError,
+ ) as e:
logger.opt(colors=True, exception=e).error(
f"Error while connecting to {escape_tag(str(url))}. "
- "Try to reconnect...")
+ "Try to reconnect..."
+ )
finally:
if bot:
self._bot_disconnect(bot)
@@ -395,7 +414,8 @@ class Driver(ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Unexpected exception occurred "
- "while websocket loop")
+ "while websocket loop"
+ )
@dataclass
diff --git a/nonebot/drivers/fastapi.py b/nonebot/drivers/fastapi.py
index e0d47d79..db9abf41 100644
--- a/nonebot/drivers/fastapi.py
+++ b/nonebot/drivers/fastapi.py
@@ -32,11 +32,15 @@ from nonebot.typing import overrides
from nonebot.utils import escape_tag
from nonebot.config import Config as NoneBotConfig
from nonebot.drivers import WebSocket as BaseWebSocket
-from nonebot.drivers import (HTTPRequest, ForwardDriver, ReverseDriver,
- WebSocketSetup, HTTPPollingSetup)
+from nonebot.drivers import (
+ HTTPRequest,
+ ForwardDriver,
+ ReverseDriver,
+ WebSocketSetup,
+ HTTPPollingSetup,
+)
-HTTPPOLLING_SETUP = Union[HTTPPollingSetup,
- Callable[[], Awaitable[HTTPPollingSetup]]]
+HTTPPOLLING_SETUP = Union[HTTPPollingSetup, Callable[[], Awaitable[HTTPPollingSetup]]]
WEBSOCKET_SETUP = Union[WebSocketSetup, Callable[[], Awaitable[WebSocketSetup]]]
@@ -44,6 +48,7 @@ class Config(BaseSettings):
"""
FastAPI 驱动框架设置,详情参考 FastAPI 文档
"""
+
fastapi_openapi_url: Optional[str] = None
"""
:类型:
@@ -226,12 +231,14 @@ class Driver(ReverseDriver, ForwardDriver):
self.websockets.append(setup)
@overrides(ReverseDriver)
- def run(self,
- host: Optional[str] = None,
- port: Optional[int] = None,
- *,
- app: Optional[str] = None,
- **kwargs):
+ def run(
+ self,
+ host: Optional[str] = None,
+ port: Optional[int] = None,
+ *,
+ app: Optional[str] = None,
+ **kwargs,
+ ):
"""使用 ``uvicorn`` 启动 FastAPI"""
super().run(host, port, app, **kwargs)
LOGGING_CONFIG = {
@@ -243,10 +250,7 @@ class Driver(ReverseDriver, ForwardDriver):
},
},
"loggers": {
- "uvicorn.error": {
- "handlers": ["default"],
- "level": "INFO"
- },
+ "uvicorn.error": {"handlers": ["default"], "level": "INFO"},
"uvicorn.access": {
"handlers": ["default"],
"level": "INFO",
@@ -258,15 +262,16 @@ class Driver(ReverseDriver, ForwardDriver):
host=host or str(self.config.host),
port=port or self.config.port,
reload=self.fastapi_config.fastapi_reload
- if self.fastapi_config.fastapi_reload is not None else
- (bool(app) and self.config.debug),
+ if self.fastapi_config.fastapi_reload is not None
+ else (bool(app) and self.config.debug),
reload_dirs=self.fastapi_config.fastapi_reload_dirs,
reload_delay=self.fastapi_config.fastapi_reload_delay,
reload_includes=self.fastapi_config.fastapi_reload_includes,
reload_excludes=self.fastapi_config.fastapi_reload_excludes,
debug=self.config.debug,
log_config=LOGGING_CONFIG,
- **kwargs)
+ **kwargs,
+ )
def _run_forward(self):
for setup in self.http_pollings:
@@ -287,39 +292,49 @@ class Driver(ReverseDriver, ForwardDriver):
logger.warning(
f"Unknown adapter {adapter}. Please register the adapter before use."
)
- raise HTTPException(status_code=status.HTTP_404_NOT_FOUND,
- detail="adapter not found")
+ raise HTTPException(
+ status_code=status.HTTP_404_NOT_FOUND, detail="adapter not found"
+ )
# 创建 Bot 对象
BotClass = self._adapters[adapter]
- http_request = HTTPRequest(request.scope["http_version"],
- request.url.scheme, request.url.path,
- request.scope["query_string"],
- dict(request.headers), request.method, data)
- x_self_id, response = await BotClass.check_permission(
- self, http_request)
+ http_request = HTTPRequest(
+ request.scope["http_version"],
+ request.url.scheme,
+ request.url.path,
+ request.scope["query_string"],
+ dict(request.headers),
+ request.method,
+ data,
+ )
+ x_self_id, response = await BotClass.check_permission(self, http_request)
if not x_self_id:
raise HTTPException(
- response and response.status or 401, response and
- response.body and response.body.decode("utf-8"))
+ response and response.status or 401,
+ response and response.body and response.body.decode("utf-8"),
+ )
if x_self_id in self._clients:
- logger.warning("There's already a reverse websocket connection,"
- "so the event may be handled twice.")
+ logger.warning(
+ "There's already a reverse websocket connection,"
+ "so the event may be handled twice."
+ )
bot = BotClass(x_self_id, http_request)
asyncio.create_task(bot.handle_message(data))
- return Response(response and response.body,
- response and response.status or 200)
+ return Response(response and response.body, response and response.status or 200)
- async def _handle_ws_reverse(self, adapter: str,
- websocket: FastAPIWebSocket):
- ws = WebSocket(websocket.scope.get("http_version",
- "1.1"), websocket.url.scheme,
- websocket.url.path, websocket.scope["query_string"],
- dict(websocket.headers), websocket)
+ async def _handle_ws_reverse(self, adapter: str, websocket: FastAPIWebSocket):
+ ws = WebSocket(
+ websocket.scope.get("http_version", "1.1"),
+ websocket.url.scheme,
+ websocket.url.path,
+ websocket.scope["query_string"],
+ dict(websocket.headers),
+ websocket,
+ )
if adapter not in self._adapters:
logger.warning(
@@ -349,7 +364,8 @@ class Driver(ReverseDriver, ForwardDriver):
await ws.accept()
logger.opt(colors=True).info(
f"WebSocket Connection from {escape_tag(adapter.upper())} "
- f"Bot {escape_tag(self_id)} Accepted!")
+ f"Bot {escape_tag(self_id)} Accepted!"
+ )
self._bot_connect(bot)
@@ -362,7 +378,8 @@ class Driver(ReverseDriver, ForwardDriver):
break
except Exception as e:
logger.opt(exception=e).error(
- "Error when receiving data from websocket.")
+ "Error when receiving data from websocket."
+ )
break
asyncio.create_task(bot.handle_message(data.encode()))
@@ -370,9 +387,7 @@ class Driver(ReverseDriver, ForwardDriver):
self._bot_disconnect(bot)
async def _http_loop(self, setup: HTTPPOLLING_SETUP):
-
- async def _build_request(
- setup: HTTPPollingSetup) -> Optional[HTTPRequest]:
+ async def _build_request(setup: HTTPPollingSetup) -> Optional[HTTPRequest]:
url = httpx.URL(setup.url)
if not url.netloc:
logger.opt(colors=True).error(
@@ -380,9 +395,14 @@ class Driver(ReverseDriver, ForwardDriver):
)
return
return HTTPRequest(
- setup.http_version, url.scheme, url.path, url.query, {
- **setup.headers, "host": url.netloc.decode("ascii")
- }, setup.method, setup.body)
+ setup.http_version,
+ url.scheme,
+ url.path,
+ url.query,
+ {**setup.headers, "host": url.netloc.decode("ascii")},
+ setup.method,
+ setup.body,
+ )
bot: Optional[Bot] = None
request: Optional[HTTPRequest] = None
@@ -390,11 +410,11 @@ class Driver(ReverseDriver, ForwardDriver):
logger.opt(colors=True).info(
f"Start http polling for {escape_tag(setup.adapter.upper())} "
- f"Bot {escape_tag(setup.self_id)}")
+ f"Bot {escape_tag(setup.self_id)}"
+ )
try:
- async with httpx.AsyncClient(http2=True,
- follow_redirects=True) as session:
+ async with httpx.AsyncClient(http2=True, follow_redirects=True) as session:
while not self.shutdown.is_set():
try:
@@ -405,7 +425,8 @@ class Driver(ReverseDriver, ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error while parsing setup "
- f"{escape_tag(repr(setup))}.")
+ f"{escape_tag(repr(setup))}."
+ )
await asyncio.sleep(3)
continue
@@ -432,18 +453,21 @@ class Driver(ReverseDriver, ForwardDriver):
f"Bot {setup_.self_id} from adapter {setup_.adapter} request {setup_.url}"
)
try:
- response = await session.request(request.method,
- setup_.url,
- content=request.body,
- headers=headers,
- timeout=30.)
+ response = await session.request(
+ request.method,
+ setup_.url,
+ content=request.body,
+ headers=headers,
+ timeout=30.0,
+ )
response.raise_for_status()
data = response.read()
asyncio.create_task(bot.handle_message(data))
except httpx.HTTPError as e:
logger.opt(colors=True, exception=e).error(
f"Error occurred while requesting {escape_tag(setup_.url)}. "
- "Try to reconnect...")
+ "Try to reconnect..."
+ )
await asyncio.sleep(setup_.poll_interval)
@@ -452,7 +476,8 @@ class Driver(ReverseDriver, ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Unexpected exception occurred "
- "while http polling")
+ "while http polling"
+ )
finally:
if bot:
self._bot_disconnect(bot)
@@ -471,7 +496,8 @@ class Driver(ReverseDriver, ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error while parsing setup "
- f"{escape_tag(repr(setup))}.")
+ f"{escape_tag(repr(setup))}."
+ )
await asyncio.sleep(3)
continue
@@ -491,9 +517,11 @@ class Driver(ReverseDriver, ForwardDriver):
async with connection as ws:
logger.opt(colors=True).info(
f"WebSocket Connection to {escape_tag(setup_.adapter.upper())} "
- f"Bot {escape_tag(setup_.self_id)} succeeded!")
- request = WebSocket("1.1", url.scheme, url.path,
- url.query, headers, ws)
+ f"Bot {escape_tag(setup_.self_id)} succeeded!"
+ )
+ request = WebSocket(
+ "1.1", url.scheme, url.path, url.query, headers, ws
+ )
BotClass = self._adapters[setup_.adapter]
bot = BotClass(setup_.self_id, request)
@@ -506,12 +534,14 @@ class Driver(ReverseDriver, ForwardDriver):
except ConnectionClosed:
logger.opt(colors=True).error(
"WebSocket connection closed by peer. "
- "Try to reconnect...")
+ "Try to reconnect..."
+ )
break
except Exception as e:
logger.opt(colors=True, exception=e).error(
f"Error while connecting to {url}. "
- "Try to reconnect...")
+ "Try to reconnect..."
+ )
finally:
if bot:
self._bot_disconnect(bot)
@@ -523,21 +553,22 @@ class Driver(ReverseDriver, ForwardDriver):
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Unexpected exception occurred "
- "while websocket loop")
+ "while websocket loop"
+ )
@dataclass
class WebSocket(BaseWebSocket):
- websocket: Union[FastAPIWebSocket,
- WebSocketClientProtocol] = None # type: ignore
+ websocket: Union[FastAPIWebSocket, WebSocketClientProtocol] = None # type: ignore
@property
@overrides(BaseWebSocket)
def closed(self) -> bool:
if isinstance(self.websocket, FastAPIWebSocket):
return (
- self.websocket.client_state == WebSocketState.DISCONNECTED or
- self.websocket.application_state == WebSocketState.DISCONNECTED)
+ self.websocket.client_state == WebSocketState.DISCONNECTED
+ or self.websocket.application_state == WebSocketState.DISCONNECTED
+ )
else:
return self.websocket.closed
diff --git a/nonebot/drivers/quart.py b/nonebot/drivers/quart.py
index 5359c270..79055eb9 100644
--- a/nonebot/drivers/quart.py
+++ b/nonebot/drivers/quart.py
@@ -30,8 +30,7 @@ try:
from quart import Quart, Request, Response
from quart import Websocket as QuartWebSocket
except ImportError:
- raise ValueError(
- 'Please install Quart by using `pip install nonebot2[quart]`')
+ raise ValueError("Please install Quart by using `pip install nonebot2[quart]`")
_AsyncCallable = TypeVar("_AsyncCallable", bound=Callable[..., Coroutine])
@@ -40,6 +39,7 @@ class Config(BaseSettings):
"""
Quart 驱动框架设置
"""
+
quart_reload: Optional[bool] = None
"""
:类型:
@@ -111,11 +111,12 @@ class Driver(ReverseDriver):
self.quart_config = Config(**config.dict())
self._server_app = Quart(self.__class__.__qualname__)
- self._server_app.add_url_rule("//http",
- methods=["POST"],
- view_func=self._handle_http)
- self._server_app.add_websocket("//ws",
- view_func=self._handle_ws_reverse)
+ self._server_app.add_url_rule(
+ "//http", methods=["POST"], view_func=self._handle_http
+ )
+ self._server_app.add_websocket(
+ "//ws", view_func=self._handle_ws_reverse
+ )
@property
@overrides(ReverseDriver)
@@ -156,12 +157,14 @@ class Driver(ReverseDriver):
return self.server_app.after_serving(func) # type: ignore
@overrides(ReverseDriver)
- def run(self,
- host: Optional[str] = None,
- port: Optional[int] = None,
- *,
- app: Optional[str] = None,
- **kwargs):
+ def run(
+ self,
+ host: Optional[str] = None,
+ port: Optional[int] = None,
+ *,
+ app: Optional[str] = None,
+ **kwargs,
+ ):
"""使用 ``uvicorn`` 启动 Quart"""
super().run(host, port, app, **kwargs)
LOGGING_CONFIG = {
@@ -173,10 +176,7 @@ class Driver(ReverseDriver):
},
},
"loggers": {
- "uvicorn.error": {
- "handlers": ["default"],
- "level": "INFO"
- },
+ "uvicorn.error": {"handlers": ["default"], "level": "INFO"},
"uvicorn.access": {
"handlers": ["default"],
"level": "INFO",
@@ -188,52 +188,69 @@ class Driver(ReverseDriver):
host=host or str(self.config.host),
port=port or self.config.port,
reload=self.quart_config.quart_reload
- if self.quart_config.quart_reload is not None else
- (bool(app) and self.config.debug),
+ if self.quart_config.quart_reload is not None
+ else (bool(app) and self.config.debug),
reload_dirs=self.quart_config.quart_reload_dirs,
reload_delay=self.quart_config.quart_reload_delay,
reload_includes=self.quart_config.quart_reload_includes,
reload_excludes=self.quart_config.quart_reload_excludes,
debug=self.config.debug,
log_config=LOGGING_CONFIG,
- **kwargs)
+ **kwargs,
+ )
async def _handle_http(self, adapter: str):
request: Request = _request
data: bytes = await request.get_data() # type: ignore
if adapter not in self._adapters:
- logger.warning(f'Unknown adapter {adapter}. '
- 'Please register the adapter before use.')
+ logger.warning(
+ f"Unknown adapter {adapter}. " "Please register the adapter before use."
+ )
raise exceptions.NotFound()
BotClass = self._adapters[adapter]
- http_request = HTTPRequest(request.http_version, request.scheme,
- request.path, request.query_string,
- dict(request.headers), request.method, data)
+ http_request = HTTPRequest(
+ request.http_version,
+ request.scheme,
+ request.path,
+ request.query_string,
+ dict(request.headers),
+ request.method,
+ data,
+ )
self_id, response = await BotClass.check_permission(self, http_request)
if not self_id:
raise exceptions.Unauthorized(
- description=(response and response.body or b"").decode())
+ description=(response and response.body or b"").decode()
+ )
if self_id in self._clients:
- logger.warning("There's already a reverse websocket connection,"
- "so the event may be handled twice.")
+ logger.warning(
+ "There's already a reverse websocket connection,"
+ "so the event may be handled twice."
+ )
bot = BotClass(self_id, http_request)
asyncio.create_task(bot.handle_message(data))
- return Response(response and response.body or "",
- response and response.status or 200)
+ return Response(
+ response and response.body or "", response and response.status or 200
+ )
async def _handle_ws_reverse(self, adapter: str):
websocket: QuartWebSocket = _websocket
- ws = WebSocket(websocket.http_version, websocket.scheme,
- websocket.path, websocket.query_string,
- dict(websocket.headers), websocket)
+ ws = WebSocket(
+ websocket.http_version,
+ websocket.scheme,
+ websocket.path,
+ websocket.query_string,
+ dict(websocket.headers),
+ websocket,
+ )
if adapter not in self._adapters:
logger.warning(
- f'Unknown adapter {adapter}. Please register the adapter before use.'
+ f"Unknown adapter {adapter}. Please register the adapter before use."
)
raise exceptions.NotFound()
@@ -242,20 +259,22 @@ class Driver(ReverseDriver):
if not self_id:
raise exceptions.Unauthorized(
- description=(response and response.body or b"").decode())
+ description=(response and response.body or b"").decode()
+ )
if self_id in self._clients:
logger.opt(colors=True).warning(
"There's already a websocket connection, "
f"{escape_tag(adapter.upper())} Bot {escape_tag(self_id)} ignored."
)
- raise exceptions.Forbidden(description='Client already exists.')
+ raise exceptions.Forbidden(description="Client already exists.")
bot = BotClass(self_id, ws)
await ws.accept()
logger.opt(colors=True).info(
f"WebSocket Connection from {escape_tag(adapter.upper())} "
- f"Bot {escape_tag(self_id)} Accepted!")
+ f"Bot {escape_tag(self_id)} Accepted!"
+ )
self._bot_connect(bot)
try:
@@ -267,7 +286,8 @@ class Driver(ReverseDriver):
break
except Exception as e:
logger.opt(exception=e).error(
- "Error when receiving data from websocket.")
+ "Error when receiving data from websocket."
+ )
break
asyncio.create_task(bot.handle_message(data.encode()))
diff --git a/nonebot/exception.py b/nonebot/exception.py
index 227d8e10..e602ee93 100644
--- a/nonebot/exception.py
+++ b/nonebot/exception.py
@@ -157,6 +157,7 @@ class NoLogException(AdapterException):
指示 NoneBot 对当前 ``Event`` 进行处理但不显示 Log 信息,可在 ``get_log_string`` 时抛出
"""
+
pass
@@ -166,6 +167,7 @@ class ApiNotAvailable(AdapterException):
在 API 连接不可用时抛出。
"""
+
pass
@@ -175,6 +177,7 @@ class NetworkError(AdapterException):
在网络出现问题时抛出,如: API 请求地址不正确, API 请求无返回或返回状态非正常等。
"""
+
pass
@@ -184,4 +187,5 @@ class ActionFailed(AdapterException):
API 请求成功返回数据,但 API 操作失败。
"""
+
pass
diff --git a/nonebot/handler.py b/nonebot/handler.py
index 6203bebd..78ec21b9 100644
--- a/nonebot/handler.py
+++ b/nonebot/handler.py
@@ -10,20 +10,27 @@ from contextlib import AsyncExitStack
from typing import Any, Dict, List, Type, Callable, Optional
from nonebot.utils import get_name, run_sync
-from nonebot.dependencies import (Param, Dependent, DependsWrapper,
- get_dependent, solve_dependencies,
- get_parameterless_sub_dependant)
+from nonebot.dependencies import (
+ Param,
+ Dependent,
+ DependsWrapper,
+ get_dependent,
+ solve_dependencies,
+ get_parameterless_sub_dependant,
+)
class Handler:
"""事件处理器类。支持依赖注入。"""
- def __init__(self,
- func: Callable[..., Any],
- *,
- name: Optional[str] = None,
- dependencies: Optional[List[DependsWrapper]] = None,
- allow_types: Optional[List[Type[Param]]] = None):
+ def __init__(
+ self,
+ func: Callable[..., Any],
+ *,
+ name: Optional[str] = None,
+ dependencies: Optional[List[DependsWrapper]] = None,
+ allow_types: Optional[List[Type[Param]]] = None,
+ ):
"""
:说明:
@@ -64,19 +71,18 @@ class Handler:
self.dependent = get_dependent(func=func, allow_types=self.allow_types)
def __repr__(self) -> str:
- return (
- f""
- )
+ return f""
def __str__(self) -> str:
return repr(self)
- async def __call__(self,
- *,
- _stack: Optional[AsyncExitStack] = None,
- _dependency_cache: Optional[Dict[Callable[..., Any],
- Any]] = None,
- **params) -> Any:
+ async def __call__(
+ self,
+ *,
+ _stack: Optional[AsyncExitStack] = None,
+ _dependency_cache: Optional[Dict[Callable[..., Any], Any]] = None,
+ **params,
+ ) -> Any:
values, _ = await solve_dependencies(
_dependent=self.dependent,
_stack=_stack,
@@ -85,7 +91,8 @@ class Handler:
for dependency in self.dependencies
],
_dependency_cache=_dependency_cache,
- **params)
+ **params,
+ )
if asyncio.iscoroutinefunction(self.func):
return await self.func(**values)
@@ -98,7 +105,8 @@ class Handler:
if dependency.dependency in self.sub_dependents:
raise ValueError(f"{dependency} is already in dependencies")
sub_dependant = get_parameterless_sub_dependant(
- depends=dependency, allow_types=self.allow_types)
+ depends=dependency, allow_types=self.allow_types
+ )
self.sub_dependents[dependency.dependency] = sub_dependant
def prepend_dependency(self, dependency: DependsWrapper):
diff --git a/nonebot/log.py b/nonebot/log.py
index 8b1cc38c..8541f6b8 100644
--- a/nonebot/log.py
+++ b/nonebot/log.py
@@ -48,7 +48,6 @@ logger: "Logger" = loguru.logger
class Filter:
-
def __init__(self) -> None:
self.level: Union[int, str] = "DEBUG"
@@ -58,13 +57,13 @@ class Filter:
if module:
module_name = getattr(module, "__module_name__", module_name)
record["name"] = module_name.split(".")[0]
- levelno = logger.level(self.level).no if isinstance(self.level,
- str) else self.level
+ levelno = (
+ logger.level(self.level).no if isinstance(self.level, str) else self.level
+ )
return record["level"].no >= levelno
class LoguruHandler(logging.Handler):
-
def emit(self, record):
try:
level = logger.level(record.levelname).name
@@ -76,8 +75,9 @@ class LoguruHandler(logging.Handler):
frame = frame.f_back
depth += 1
- logger.opt(depth=depth,
- exception=record.exc_info).log(level, record.getMessage())
+ logger.opt(depth=depth, exception=record.exc_info).log(
+ level, record.getMessage()
+ )
logger.remove()
@@ -87,9 +87,12 @@ default_format = (
"[{level}] "
"{name} | "
# "{function}:{line}| "
- "{message}")
-logger_id = logger.add(sys.stdout,
- colorize=True,
- diagnose=False,
- filter=default_filter,
- format=default_format)
+ "{message}"
+)
+logger_id = logger.add(
+ sys.stdout,
+ colorize=True,
+ diagnose=False,
+ filter=default_filter,
+ format=default_format,
+)
diff --git a/nonebot/matcher.py b/nonebot/matcher.py
index cbaab224..6f42dcf2 100644
--- a/nonebot/matcher.py
+++ b/nonebot/matcher.py
@@ -10,8 +10,17 @@ from datetime import datetime
from contextvars import ContextVar
from collections import defaultdict
from contextlib import AsyncExitStack
-from typing import (TYPE_CHECKING, Any, Dict, List, Type, Union, Callable,
- NoReturn, Optional)
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Dict,
+ List,
+ Type,
+ Union,
+ Callable,
+ NoReturn,
+ Optional,
+)
from nonebot import params
from nonebot.rule import Rule
@@ -19,14 +28,29 @@ from nonebot.log import logger
from nonebot.handler import Handler
from nonebot.dependencies import DependsWrapper
from nonebot.permission import USER, Permission
-from nonebot.adapters import (Bot, Event, Message, MessageSegment,
- MessageTemplate)
-from nonebot.exception import (PausedException, StopPropagation,
- SkippedException, FinishedException,
- RejectedException)
-from nonebot.typing import (T_State, T_Handler, T_ArgsParser, T_TypeUpdater,
- T_StateFactory, T_DependencyCache,
- T_PermissionUpdater)
+from nonebot.adapters import (
+ Bot,
+ Event,
+ Message,
+ MessageSegment,
+ MessageTemplate,
+)
+from nonebot.exception import (
+ PausedException,
+ StopPropagation,
+ SkippedException,
+ FinishedException,
+ RejectedException,
+)
+from nonebot.typing import (
+ T_State,
+ T_Handler,
+ T_ArgsParser,
+ T_TypeUpdater,
+ T_StateFactory,
+ T_DependencyCache,
+ T_PermissionUpdater,
+)
if TYPE_CHECKING:
from nonebot.plugin import Plugin
@@ -57,9 +81,11 @@ class MatcherMeta(type):
expire_time: Optional[datetime]
def __repr__(self) -> str:
- return (f"")
+ return (
+ f""
+ )
def __str__(self) -> str:
return repr(self)
@@ -67,6 +93,7 @@ class MatcherMeta(type):
class Matcher(metaclass=MatcherMeta):
"""事件响应器类"""
+
plugin: Optional["Plugin"] = None
"""
:类型: ``Optional[Plugin]``
@@ -157,8 +184,11 @@ class Matcher(metaclass=MatcherMeta):
"""
HANDLER_PARAM_TYPES = [
- params.BotParam, params.EventParam, params.StateParam,
- params.MatcherParam, params.DefaultParam
+ params.BotParam,
+ params.EventParam,
+ params.StateParam,
+ params.MatcherParam,
+ params.DefaultParam,
]
def __init__(self):
@@ -169,7 +199,8 @@ class Matcher(metaclass=MatcherMeta):
def __repr__(self) -> str:
return (
f"")
+ f"priority={self.priority}, temp={self.temp}>"
+ )
def __str__(self) -> str:
return repr(self)
@@ -180,8 +211,9 @@ class Matcher(metaclass=MatcherMeta):
type_: str = "",
rule: Optional[Rule] = None,
permission: Optional[Permission] = None,
- handlers: Optional[Union[List[T_Handler], List[Handler],
- List[Union[T_Handler, Handler]]]] = None,
+ handlers: Optional[
+ Union[List[T_Handler], List[Handler], List[Union[T_Handler, Handler]]]
+ ] = None,
temp: bool = False,
priority: int = 1,
block: bool = False,
@@ -193,7 +225,7 @@ class Matcher(metaclass=MatcherMeta):
default_state_factory: Optional[T_StateFactory] = None,
default_parser: Optional[T_ArgsParser] = None,
default_type_updater: Optional[T_TypeUpdater] = None,
- default_permission_updater: Optional[T_PermissionUpdater] = None
+ default_permission_updater: Optional[T_PermissionUpdater] = None,
) -> Type["Matcher"]:
"""
:说明:
@@ -221,46 +253,37 @@ class Matcher(metaclass=MatcherMeta):
"""
NewMatcher = type(
- "Matcher", (Matcher,), {
- "plugin":
- plugin,
- "module":
- module,
- "plugin_name":
- plugin and plugin.name,
- "module_name":
- module and module.__name__,
- "type":
- type_,
- "rule":
- rule or Rule(),
- "permission":
- permission or Permission(),
+ "Matcher",
+ (Matcher,),
+ {
+ "plugin": plugin,
+ "module": module,
+ "plugin_name": plugin and plugin.name,
+ "module_name": module and module.__name__,
+ "type": type_,
+ "rule": rule or Rule(),
+ "permission": permission or Permission(),
"handlers": [
- handler if isinstance(handler, Handler) else Handler(
- handler, allow_types=cls.HANDLER_PARAM_TYPES)
+ handler
+ if isinstance(handler, Handler)
+ else Handler(handler, allow_types=cls.HANDLER_PARAM_TYPES)
for handler in handlers
- ] if handlers else [],
- "temp":
- temp,
- "expire_time":
- expire_time,
- "priority":
- priority,
- "block":
- block,
- "_default_state":
- default_state or {},
- "_default_state_factory":
- staticmethod(default_state_factory)
- if default_state_factory else None,
- "_default_parser":
- default_parser,
- "_default_type_updater":
- default_type_updater,
- "_default_permission_updater":
- default_permission_updater
- })
+ ]
+ if handlers
+ else [],
+ "temp": temp,
+ "expire_time": expire_time,
+ "priority": priority,
+ "block": block,
+ "_default_state": default_state or {},
+ "_default_state_factory": staticmethod(default_state_factory)
+ if default_state_factory
+ else None,
+ "_default_parser": default_parser,
+ "_default_type_updater": default_type_updater,
+ "_default_permission_updater": default_permission_updater,
+ },
+ )
matchers[priority].append(NewMatcher)
@@ -272,8 +295,8 @@ class Matcher(metaclass=MatcherMeta):
bot: Bot,
event: Event,
stack: Optional[AsyncExitStack] = None,
- dependency_cache: Optional[Dict[Callable[..., Any],
- Any]] = None) -> bool:
+ dependency_cache: Optional[Dict[Callable[..., Any], Any]] = None,
+ ) -> bool:
"""
:说明:
@@ -289,8 +312,9 @@ class Matcher(metaclass=MatcherMeta):
- ``bool``: 是否满足权限
"""
event_type = event.get_type()
- return (event_type == (cls.type or event_type) and
- await cls.permission(bot, event, stack, dependency_cache))
+ return event_type == (cls.type or event_type) and await cls.permission(
+ bot, event, stack, dependency_cache
+ )
@classmethod
async def check_rule(
@@ -299,8 +323,8 @@ class Matcher(metaclass=MatcherMeta):
event: Event,
state: T_State,
stack: Optional[AsyncExitStack] = None,
- dependency_cache: Optional[Dict[Callable[..., Any],
- Any]] = None) -> bool:
+ dependency_cache: Optional[Dict[Callable[..., Any], Any]] = None,
+ ) -> bool:
"""
:说明:
@@ -317,8 +341,9 @@ class Matcher(metaclass=MatcherMeta):
- ``bool``: 是否满足匹配规则
"""
event_type = event.get_type()
- return (event_type == (cls.type or event_type) and
- await cls.rule(bot, event, state, stack, dependency_cache))
+ return event_type == (cls.type or event_type) and await cls.rule(
+ bot, event, state, stack, dependency_cache
+ )
@classmethod
def args_parser(cls, func: T_ArgsParser) -> T_ArgsParser:
@@ -349,8 +374,7 @@ class Matcher(metaclass=MatcherMeta):
return func
@classmethod
- def permission_updater(cls,
- func: T_PermissionUpdater) -> T_PermissionUpdater:
+ def permission_updater(cls, func: T_PermissionUpdater) -> T_PermissionUpdater:
"""
:说明:
@@ -365,12 +389,11 @@ class Matcher(metaclass=MatcherMeta):
@classmethod
def append_handler(
- cls,
- handler: T_Handler,
- dependencies: Optional[List[DependsWrapper]] = None) -> Handler:
- handler_ = Handler(handler,
- dependencies=dependencies,
- allow_types=cls.HANDLER_PARAM_TYPES)
+ cls, handler: T_Handler, dependencies: Optional[List[DependsWrapper]] = None
+ ) -> Handler:
+ handler_ = Handler(
+ handler, dependencies=dependencies, allow_types=cls.HANDLER_PARAM_TYPES
+ )
cls.handlers.append(handler_)
return handler_
@@ -418,8 +441,7 @@ class Matcher(metaclass=MatcherMeta):
func_handler = cls.handlers[-1]
func_handler.prepend_dependency(depend)
else:
- cls.append_handler(
- func, dependencies=[depend] if cls.handlers else [])
+ cls.append_handler(func, dependencies=[depend] if cls.handlers else [])
return func
@@ -429,9 +451,8 @@ class Matcher(metaclass=MatcherMeta):
def got(
cls,
key: str,
- prompt: Optional[Union[str, Message, MessageSegment,
- MessageTemplate]] = None,
- args_parser: Optional[T_ArgsParser] = None
+ prompt: Optional[Union[str, Message, MessageSegment, MessageTemplate]] = None,
+ args_parser: Optional[T_ArgsParser] = None,
) -> Callable[[T_Handler], T_Handler]:
"""
:说明:
@@ -483,16 +504,16 @@ class Matcher(metaclass=MatcherMeta):
func_handler.prepend_dependency(parser_depend)
func_handler.prepend_dependency(get_depend)
else:
- cls.append_handler(func,
- dependencies=[get_depend, parser_depend])
+ cls.append_handler(func, dependencies=[get_depend, parser_depend])
return func
return _decorator
@classmethod
- async def send(cls, message: Union[str, Message, MessageSegment,
- MessageTemplate], **kwargs) -> Any:
+ async def send(
+ cls, message: Union[str, Message, MessageSegment, MessageTemplate], **kwargs
+ ) -> Any:
"""
:说明:
@@ -513,10 +534,11 @@ class Matcher(metaclass=MatcherMeta):
return await bot.send(event=event, message=_message, **kwargs)
@classmethod
- async def finish(cls,
- message: Optional[Union[str, Message, MessageSegment,
- MessageTemplate]] = None,
- **kwargs) -> NoReturn:
+ async def finish(
+ cls,
+ message: Optional[Union[str, Message, MessageSegment, MessageTemplate]] = None,
+ **kwargs,
+ ) -> NoReturn:
"""
:说明:
@@ -539,10 +561,11 @@ class Matcher(metaclass=MatcherMeta):
raise FinishedException
@classmethod
- async def pause(cls,
- prompt: Optional[Union[str, Message, MessageSegment,
- MessageTemplate]] = None,
- **kwargs) -> NoReturn:
+ async def pause(
+ cls,
+ prompt: Optional[Union[str, Message, MessageSegment, MessageTemplate]] = None,
+ **kwargs,
+ ) -> NoReturn:
"""
:说明:
@@ -565,10 +588,9 @@ class Matcher(metaclass=MatcherMeta):
raise PausedException
@classmethod
- async def reject(cls,
- prompt: Optional[Union[str, Message,
- MessageSegment]] = None,
- **kwargs) -> NoReturn:
+ async def reject(
+ cls, prompt: Optional[Union[str, Message, MessageSegment]] = None, **kwargs
+ ) -> NoReturn:
"""
:说明:
@@ -601,31 +623,38 @@ class Matcher(metaclass=MatcherMeta):
self.block = True
# 运行handlers
- async def run(self,
- bot: Bot,
- event: Event,
- state: T_State,
- stack: Optional[AsyncExitStack] = None,
- dependency_cache: Optional[T_DependencyCache] = None):
+ async def run(
+ self,
+ bot: Bot,
+ event: Event,
+ state: T_State,
+ stack: Optional[AsyncExitStack] = None,
+ dependency_cache: Optional[T_DependencyCache] = None,
+ ):
b_t = current_bot.set(bot)
e_t = current_event.set(event)
s_t = current_state.set(self.state)
try:
# Refresh preprocess state
- self.state = await self._default_state_factory(
- bot, event) if self._default_state_factory else self.state
+ self.state = (
+ await self._default_state_factory(bot, event)
+ if self._default_state_factory
+ else self.state
+ )
self.state.update(state)
while self.handlers:
handler = self.handlers.pop(0)
logger.debug(f"Running handler {handler}")
try:
- await handler(matcher=self,
- bot=bot,
- event=event,
- state=self.state,
- _stack=stack,
- _dependency_cache=dependency_cache)
+ await handler(
+ matcher=self,
+ bot=bot,
+ event=event,
+ state=self.state,
+ _stack=stack,
+ _dependency_cache=dependency_cache,
+ )
except SkippedException:
pass
@@ -633,18 +662,13 @@ class Matcher(metaclass=MatcherMeta):
self.handlers.insert(0, handler) # type: ignore
updater = self.__class__._default_type_updater
if updater:
- type_ = await updater(
- bot,
- event,
- self.state, # type: ignore
- self.type)
+ type_ = await updater(bot, event, self.state, self.type) # type: ignore
else:
type_ = "message"
updater = self.__class__._default_permission_updater
if updater:
- permission = await updater(bot, event, self.state,
- self.permission)
+ permission = await updater(bot, event, self.state, self.permission)
else:
permission = USER(event.get_session_id(), perm=self.permission)
@@ -662,23 +686,18 @@ class Matcher(metaclass=MatcherMeta):
default_state=self.state,
default_parser=self.__class__._default_parser,
default_type_updater=self.__class__._default_type_updater,
- default_permission_updater=self.__class__.
- _default_permission_updater)
+ default_permission_updater=self.__class__._default_permission_updater,
+ )
except PausedException:
updater = self.__class__._default_type_updater
if updater:
- type_ = await updater(
- bot,
- event,
- self.state, # type: ignore
- self.type)
+ type_ = await updater(bot, event, self.state, self.type) # type: ignore
else:
type_ = "message"
updater = self.__class__._default_permission_updater
if updater:
- permission = await updater(bot, event, self.state,
- self.permission)
+ permission = await updater(bot, event, self.state, self.permission)
else:
permission = USER(event.get_session_id(), perm=self.permission)
@@ -696,8 +715,8 @@ class Matcher(metaclass=MatcherMeta):
default_state=self.state,
default_parser=self.__class__._default_parser,
default_type_updater=self.__class__._default_type_updater,
- default_permission_updater=self.__class__.
- _default_permission_updater)
+ default_permission_updater=self.__class__._default_permission_updater,
+ )
except FinishedException:
pass
except StopPropagation:
diff --git a/nonebot/message.py b/nonebot/message.py
index 87184362..f2ff0ca9 100644
--- a/nonebot/message.py
+++ b/nonebot/message.py
@@ -17,9 +17,14 @@ from nonebot.handler import Handler
from nonebot.utils import escape_tag
from nonebot.matcher import Matcher, matchers
from nonebot.exception import NoLogException, StopPropagation, IgnoredException
-from nonebot.typing import (T_State, T_DependencyCache, T_RunPreProcessor,
- T_RunPostProcessor, T_EventPreProcessor,
- T_EventPostProcessor)
+from nonebot.typing import (
+ T_State,
+ T_DependencyCache,
+ T_RunPreProcessor,
+ T_RunPostProcessor,
+ T_EventPreProcessor,
+ T_EventPostProcessor,
+)
if TYPE_CHECKING:
from nonebot.adapters import Bot, Event
@@ -30,15 +35,25 @@ _run_preprocessors: Set[Handler] = set()
_run_postprocessors: Set[Handler] = set()
EVENT_PCS_PARAMS = [
- params.BotParam, params.EventParam, params.StateParam, params.DefaultParam
+ params.BotParam,
+ params.EventParam,
+ params.StateParam,
+ params.DefaultParam,
]
RUN_PREPCS_PARAMS = [
- params.MatcherParam, params.BotParam, params.EventParam, params.StateParam,
- params.DefaultParam
+ params.MatcherParam,
+ params.BotParam,
+ params.EventParam,
+ params.StateParam,
+ params.DefaultParam,
]
RUN_POSTPCS_PARAMS = [
- params.MatcherParam, params.ExceptionParam, params.BotParam,
- params.EventParam, params.StateParam, params.DefaultParam
+ params.MatcherParam,
+ params.ExceptionParam,
+ params.BotParam,
+ params.EventParam,
+ params.StateParam,
+ params.DefaultParam,
]
@@ -83,13 +98,14 @@ def run_postprocessor(func: T_RunPostProcessor) -> T_RunPostProcessor:
async def _check_matcher(
- priority: int,
- Matcher: Type[Matcher],
- bot: "Bot",
- event: "Event",
- state: T_State,
- stack: Optional[AsyncExitStack] = None,
- dependency_cache: Optional[T_DependencyCache] = None) -> None:
+ priority: int,
+ Matcher: Type[Matcher],
+ bot: "Bot",
+ event: "Event",
+ state: T_State,
+ stack: Optional[AsyncExitStack] = None,
+ dependency_cache: Optional[T_DependencyCache] = None,
+) -> None:
if Matcher.expire_time and datetime.now() > Matcher.expire_time:
try:
matchers[priority].remove(Matcher)
@@ -99,13 +115,13 @@ async def _check_matcher(
try:
if not await Matcher.check_perm(
- bot, event, stack,
- dependency_cache) or not await Matcher.check_rule(
- bot, event, state, stack, dependency_cache):
+ bot, event, stack, dependency_cache
+ ) or not await Matcher.check_rule(bot, event, state, stack, dependency_cache):
return
except Exception as e:
logger.opt(colors=True, exception=e).error(
- f"Rule check failed for {Matcher}.")
+ f"Rule check failed for {Matcher}."
+ )
return
if Matcher.temp:
@@ -118,36 +134,43 @@ async def _check_matcher(
async def _run_matcher(
- Matcher: Type[Matcher],
- bot: "Bot",
- event: "Event",
- state: T_State,
- stack: Optional[AsyncExitStack] = None,
- dependency_cache: Optional[T_DependencyCache] = None) -> None:
+ Matcher: Type[Matcher],
+ bot: "Bot",
+ event: "Event",
+ state: T_State,
+ stack: Optional[AsyncExitStack] = None,
+ dependency_cache: Optional[T_DependencyCache] = None,
+) -> None:
logger.info(f"Event will be handled by {Matcher}")
matcher = Matcher()
coros = list(
map(
- lambda x: x(matcher=matcher,
- bot=bot,
- event=event,
- state=state,
- _stack=stack,
- _dependency_cache=dependency_cache),
- _run_preprocessors))
+ lambda x: x(
+ matcher=matcher,
+ bot=bot,
+ event=event,
+ state=state,
+ _stack=stack,
+ _dependency_cache=dependency_cache,
+ ),
+ _run_preprocessors,
+ )
+ )
if coros:
try:
await asyncio.gather(*coros)
except IgnoredException:
logger.opt(colors=True).info(
- f"Matcher {matcher} running is cancelled")
+ f"Matcher {matcher} running is cancelled"
+ )
return
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running RunPreProcessors. "
- "Running cancelled!")
+ "Running cancelled!"
+ )
return
exception = None
@@ -163,14 +186,18 @@ async def _run_matcher(
coros = list(
map(
- lambda x: x(matcher=matcher,
- exception=exception,
- bot=bot,
- event=event,
- state=state,
- _stack=stack,
- _dependency_cache=dependency_cache),
- _run_postprocessors))
+ lambda x: x(
+ matcher=matcher,
+ exception=exception,
+ bot=bot,
+ event=event,
+ state=state,
+ _stack=stack,
+ _dependency_cache=dependency_cache,
+ ),
+ _run_postprocessors,
+ )
+ )
if coros:
try:
await asyncio.gather(*coros)
@@ -217,12 +244,16 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
async with AsyncExitStack() as stack:
coros = list(
map(
- lambda x: x(bot=bot,
- event=event,
- state=state,
- _stack=stack,
- _dependency_cache=dependency_cache),
- _event_preprocessors))
+ lambda x: x(
+ bot=bot,
+ event=event,
+ state=state,
+ _stack=stack,
+ _dependency_cache=dependency_cache,
+ ),
+ _event_preprocessors,
+ )
+ )
if coros:
try:
if show_log:
@@ -236,7 +267,8 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
except Exception as e:
logger.opt(colors=True, exception=e).error(
"Error when running EventPreProcessors. "
- "Event ignored!")
+ "Event ignored!"
+ )
return
# Trie Match
@@ -251,13 +283,13 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
logger.debug(f"Checking for matchers in priority {priority}...")
pending_tasks = [
- _check_matcher(priority, matcher, bot, event, state.copy(),
- stack, dependency_cache)
+ _check_matcher(
+ priority, matcher, bot, event, state.copy(), stack, dependency_cache
+ )
for matcher in matchers[priority]
]
- results = await asyncio.gather(*pending_tasks,
- return_exceptions=True)
+ results = await asyncio.gather(*pending_tasks, return_exceptions=True)
for result in results:
if not isinstance(result, Exception):
@@ -272,12 +304,16 @@ async def handle_event(bot: "Bot", event: "Event") -> None:
coros = list(
map(
- lambda x: x(bot=bot,
- event=event,
- state=state,
- _stack=stack,
- _dependency_cache=dependency_cache),
- _event_postprocessors))
+ lambda x: x(
+ bot=bot,
+ event=event,
+ state=state,
+ _stack=stack,
+ _dependency_cache=dependency_cache,
+ ),
+ _event_postprocessors,
+ )
+ )
if coros:
try:
if show_log:
diff --git a/nonebot/params.py b/nonebot/params.py
index 06fb6987..484c4d21 100644
--- a/nonebot/params.py
+++ b/nonebot/params.py
@@ -10,69 +10,61 @@ from nonebot.utils import generic_check_issubclass
class BotParam(Param):
-
@classmethod
def _check(cls, name: str, param: inspect.Parameter) -> bool:
- return generic_check_issubclass(
- param.annotation, Bot) or (param.annotation == param.empty and
- name == "bot")
+ return generic_check_issubclass(param.annotation, Bot) or (
+ param.annotation == param.empty and name == "bot"
+ )
def _solve(self, bot: Bot, **kwargs: Any) -> Any:
return bot
class EventParam(Param):
-
@classmethod
def _check(cls, name: str, param: inspect.Parameter) -> bool:
- return generic_check_issubclass(
- param.annotation, Event) or (param.annotation == param.empty and
- name == "event")
+ return generic_check_issubclass(param.annotation, Event) or (
+ param.annotation == param.empty and name == "event"
+ )
def _solve(self, event: Event, **kwargs: Any) -> Any:
return event
class StateParam(Param):
-
@classmethod
def _check(cls, name: str, param: inspect.Parameter) -> bool:
- return generic_check_issubclass(
- param.annotation, Dict) or (param.annotation == param.empty and
- name == "state")
+ return generic_check_issubclass(param.annotation, Dict) or (
+ param.annotation == param.empty and name == "state"
+ )
def _solve(self, state: T_State, **kwargs: Any) -> Any:
return state
class MatcherParam(Param):
-
@classmethod
def _check(cls, name: str, param: inspect.Parameter) -> bool:
- return generic_check_issubclass(
- param.annotation, Matcher) or (param.annotation == param.empty and
- name == "matcher")
+ return generic_check_issubclass(param.annotation, Matcher) or (
+ param.annotation == param.empty and name == "matcher"
+ )
def _solve(self, matcher: Optional["Matcher"] = None, **kwargs: Any) -> Any:
return matcher
class ExceptionParam(Param):
-
@classmethod
def _check(cls, name: str, param: inspect.Parameter) -> bool:
- return generic_check_issubclass(
- param.annotation, Exception) or (param.annotation == param.empty and
- name == "exception")
+ return generic_check_issubclass(param.annotation, Exception) or (
+ param.annotation == param.empty and name == "exception"
+ )
- def _solve(self,
- exception: Optional[Exception] = None,
- **kwargs: Any) -> Any:
+ def _solve(self, exception: Optional[Exception] = None, **kwargs: Any) -> Any:
return exception
class DefaultParam(Param):
-
@classmethod
def _check(cls, name: str, param: inspect.Parameter) -> bool:
return param.default != param.empty
diff --git a/nonebot/permission.py b/nonebot/permission.py
index 4e7e89da..7724d1dd 100644
--- a/nonebot/permission.py
+++ b/nonebot/permission.py
@@ -34,11 +34,10 @@ class Permission:
from nonebot.utils import run_sync
Permission(async_function, run_sync(sync_function))
"""
+
__slots__ = ("checkers",)
- HANDLER_PARAM_TYPES = [
- params.BotParam, params.EventParam, params.DefaultParam
- ]
+ HANDLER_PARAM_TYPES = [params.BotParam, params.EventParam, params.DefaultParam]
def __init__(self, *checkers: Union[T_PermissionChecker, Handler]) -> None:
"""
@@ -48,9 +47,11 @@ class Permission:
"""
self.checkers = set(
- checker if isinstance(checker, Handler) else Handler(
- checker, allow_types=self.HANDLER_PARAM_TYPES)
- for checker in checkers)
+ checker
+ if isinstance(checker, Handler)
+ else Handler(checker, allow_types=self.HANDLER_PARAM_TYPES)
+ for checker in checkers
+ )
"""
:说明:
@@ -66,8 +67,8 @@ class Permission:
bot: Bot,
event: Event,
stack: Optional[AsyncExitStack] = None,
- dependency_cache: Optional[Dict[Callable[..., Any],
- Any]] = None) -> bool:
+ dependency_cache: Optional[Dict[Callable[..., Any], Any]] = None,
+ ) -> bool:
"""
:说明:
@@ -87,19 +88,24 @@ class Permission:
if not self.checkers:
return True
results = await asyncio.gather(
- *(checker(bot=bot,
- event=event,
- _stack=stack,
- _dependency_cache=dependency_cache)
- for checker in self.checkers))
+ *(
+ checker(
+ bot=bot,
+ event=event,
+ _stack=stack,
+ _dependency_cache=dependency_cache,
+ )
+ for checker in self.checkers
+ )
+ )
return any(results)
def __and__(self, other) -> NoReturn:
raise RuntimeError("And operation between Permissions is not allowed.")
def __or__(
- self, other: Optional[Union["Permission",
- T_PermissionChecker]]) -> "Permission":
+ self, other: Optional[Union["Permission", T_PermissionChecker]]
+ ) -> "Permission":
if other is None:
return self
elif isinstance(other, Permission):
@@ -155,15 +161,17 @@ def USER(*user: str, perm: Optional[Permission] = None):
"""
async def _user(bot: Bot, event: Event) -> bool:
- return bool(event.get_session_id() in user and
- (perm is None or await perm(bot, event)))
+ return bool(
+ event.get_session_id() in user and (perm is None or await perm(bot, event))
+ )
return Permission(_user)
async def _superuser(bot: Bot, event: Event) -> bool:
- return (event.get_type() == "message" and
- event.get_user_id() in bot.config.superusers)
+ return (
+ event.get_type() == "message" and event.get_user_id() in bot.config.superusers
+ )
SUPERUSER = Permission(_superuser)
diff --git a/nonebot/plugin/__init__.py b/nonebot/plugin/__init__.py
index 69a34e63..e55e1180 100644
--- a/nonebot/plugin/__init__.py
+++ b/nonebot/plugin/__init__.py
@@ -9,8 +9,9 @@ from typing import List, Optional
from contextvars import ContextVar
_managers: List["PluginManager"] = []
-_current_plugin: ContextVar[Optional["Plugin"]] = ContextVar("_current_plugin",
- default=None)
+_current_plugin: ContextVar[Optional["Plugin"]] = ContextVar(
+ "_current_plugin", default=None
+)
from .on import on as on
from .manager import PluginManager
diff --git a/nonebot/plugin/export.py b/nonebot/plugin/export.py
index 9c7c3f57..2a792a01 100644
--- a/nonebot/plugin/export.py
+++ b/nonebot/plugin/export.py
@@ -33,8 +33,7 @@ class Export(dict):
return func
def __setitem__(self, key, value):
- super().__setitem__(key,
- Export(value) if isinstance(value, dict) else value)
+ super().__setitem__(key, Export(value) if isinstance(value, dict) else value)
def __setattr__(self, name, value):
self[name] = Export(value) if isinstance(value, dict) else value
diff --git a/nonebot/plugin/load.py b/nonebot/plugin/load.py
index 75850f91..bfd08918 100644
--- a/nonebot/plugin/load.py
+++ b/nonebot/plugin/load.py
@@ -49,8 +49,9 @@ def load_plugins(*plugin_dir: str) -> Set[Plugin]:
return manager.load_all_plugins()
-def load_all_plugins(module_path: Iterable[str],
- plugin_dir: Iterable[str]) -> Set[Plugin]:
+def load_all_plugins(
+ module_path: Iterable[str], plugin_dir: Iterable[str]
+) -> Set[Plugin]:
"""
:说明:
@@ -90,8 +91,7 @@ def load_from_json(file_path: str, encoding: str = "utf-8") -> Set[Plugin]:
plugins = data.get("plugins")
plugin_dirs = data.get("plugin_dirs")
assert isinstance(plugins, list), "plugins must be a list of plugin name"
- assert isinstance(plugin_dirs,
- list), "plugin_dirs must be a list of directories"
+ assert isinstance(plugin_dirs, list), "plugin_dirs must be a list of directories"
return load_all_plugins(set(plugins), set(plugin_dirs))
@@ -120,14 +120,14 @@ def load_from_toml(file_path: str, encoding: str = "utf-8") -> Set[Plugin]:
if nonebot_data:
warnings.warn(
"[nonebot.plugins] table are now deprecated. Use [tool.nonebot] instead.",
- DeprecationWarning)
+ DeprecationWarning,
+ )
else:
raise ValueError("Cannot find '[tool.nonebot]' in given toml file!")
plugins = nonebot_data.get("plugins", [])
plugin_dirs = nonebot_data.get("plugin_dirs", [])
assert isinstance(plugins, list), "plugins must be a list of plugin name"
- assert isinstance(plugin_dirs,
- list), "plugin_dirs must be a list of directories"
+ assert isinstance(plugin_dirs, list), "plugin_dirs must be a list of directories"
return load_all_plugins(plugins, plugin_dirs)
@@ -163,5 +163,5 @@ def require(name: str) -> Export:
"""
plugin = get_plugin(name) or load_plugin(name)
if not plugin:
- raise RuntimeError(f"Cannot load plugin \"{name}\"!")
+ raise RuntimeError(f'Cannot load plugin "{name}"!')
return plugin.export
diff --git a/nonebot/plugin/manager.py b/nonebot/plugin/manager.py
index e98495d0..a4b375ab 100644
--- a/nonebot/plugin/manager.py
+++ b/nonebot/plugin/manager.py
@@ -15,7 +15,6 @@ from . import _managers, _current_plugin
class PluginManager:
-
def __init__(
self,
plugins: Optional[Iterable[str]] = None,
@@ -39,14 +38,15 @@ class PluginManager:
def _previous_plugins(self) -> List[str]:
_pre_managers: List[PluginManager]
if self in _managers:
- _pre_managers = _managers[:_managers.index(self)]
+ _pre_managers = _managers[: _managers.index(self)]
else:
_pre_managers = _managers[:]
return [
*chain.from_iterable(
[*manager.plugins, *manager.searched_plugins.keys()]
- for manager in _pre_managers)
+ for manager in _pre_managers
+ )
]
def list_plugins(self) -> Set[str]:
@@ -57,13 +57,14 @@ class PluginManager:
for module_info in pkgutil.iter_modules(self.search_path):
if module_info.name.startswith("_"):
continue
- if module_info.name in searched_plugins.keys(
- ) or module_info.name in previous_plugins:
+ if (
+ module_info.name in searched_plugins.keys()
+ or module_info.name in previous_plugins
+ ):
raise RuntimeError(
f"Plugin already exists: {module_info.name}! Check your plugin name"
)
- module_spec = module_info.module_finder.find_spec(
- module_info.name, None)
+ module_spec = module_info.module_finder.find_spec(module_info.name, None)
if not module_spec:
continue
module_path = module_spec.origin
@@ -80,14 +81,15 @@ class PluginManager:
if name in self.plugins:
module = importlib.import_module(name)
elif name not in self.searched_plugins:
- raise RuntimeError(
- f"Plugin not found: {name}! Check your plugin name")
+ raise RuntimeError(f"Plugin not found: {name}! Check your plugin name")
else:
module = importlib.import_module(
- self._path_to_module_name(self.searched_plugins[name]))
+ self._path_to_module_name(self.searched_plugins[name])
+ )
logger.opt(colors=True).success(
- f'Succeeded to import "{escape_tag(name)}"')
+ f'Succeeded to import "{escape_tag(name)}"'
+ )
return getattr(module, "__plugin__", None)
except Exception as e:
logger.opt(colors=True, exception=e).error(
@@ -96,16 +98,17 @@ class PluginManager:
def load_all_plugins(self) -> Set[Plugin]:
return set(
- filter(None,
- (self.load_plugin(name) for name in self.list_plugins())))
+ filter(None, (self.load_plugin(name) for name in self.list_plugins()))
+ )
class PluginFinder(MetaPathFinder):
-
- def find_spec(self,
- fullname: str,
- path: Optional[Sequence[Union[bytes, str]]],
- target: Optional[ModuleType] = None):
+ def find_spec(
+ self,
+ fullname: str,
+ path: Optional[Sequence[Union[bytes, str]]],
+ target: Optional[ModuleType] = None,
+ ):
if _managers:
index = -1
module_spec = PathFinder.find_spec(fullname, path, target)
@@ -119,10 +122,11 @@ class PluginFinder(MetaPathFinder):
while -index <= len(_managers):
manager = _managers[index]
- if fullname in manager.plugins or module_path in manager.searched_plugins.values(
+ if (
+ fullname in manager.plugins
+ or module_path in manager.searched_plugins.values()
):
- module_spec.loader = PluginLoader(manager, fullname,
- module_origin)
+ module_spec.loader = PluginLoader(manager, fullname, module_origin)
return module_spec
index -= 1
@@ -130,7 +134,6 @@ class PluginFinder(MetaPathFinder):
class PluginLoader(SourceFileLoader):
-
def __init__(self, manager: PluginManager, fullname: str, path) -> None:
self.manager = manager
self.loaded = False
diff --git a/nonebot/plugin/on.py b/nonebot/plugin/on.py
index 5b0f2979..a60d45d5 100644
--- a/nonebot/plugin/on.py
+++ b/nonebot/plugin/on.py
@@ -10,8 +10,18 @@ from nonebot.matcher import Matcher
from .manager import _current_plugin
from nonebot.permission import Permission
from nonebot.typing import T_State, T_Handler, T_RuleChecker, T_StateFactory
-from nonebot.rule import (PREFIX_KEY, RAW_CMD_KEY, Rule, ArgumentParser, regex,
- command, keyword, endswith, startswith, shell_command)
+from nonebot.rule import (
+ PREFIX_KEY,
+ RAW_CMD_KEY,
+ Rule,
+ ArgumentParser,
+ regex,
+ command,
+ keyword,
+ endswith,
+ startswith,
+ shell_command,
+)
def _store_matcher(matcher: Type[Matcher]) -> None:
@@ -30,17 +40,19 @@ def _get_matcher_module(depth: int = 1) -> Optional[ModuleType]:
return sys.modules.get(module_name)
-def on(type: str = "",
- rule: Optional[Union[Rule, T_RuleChecker]] = None,
- permission: Optional[Permission] = None,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = None,
- temp: bool = False,
- priority: int = 1,
- block: bool = False,
- state: Optional[T_State] = None,
- state_factory: Optional[T_StateFactory] = None,
- _depth: int = 0) -> Type[Matcher]:
+def on(
+ type: str = "",
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ permission: Optional[Permission] = None,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = None,
+ temp: bool = False,
+ priority: int = 1,
+ block: bool = False,
+ state: Optional[T_State] = None,
+ state_factory: Optional[T_StateFactory] = None,
+ _depth: int = 0,
+) -> Type[Matcher]:
"""
:说明:
@@ -62,30 +74,34 @@ def on(type: str = "",
- ``Type[Matcher]``
"""
- matcher = Matcher.new(type,
- Rule() & rule,
- permission or Permission(),
- temp=temp,
- priority=priority,
- block=block,
- handlers=handlers,
- plugin=_current_plugin.get(),
- module=_get_matcher_module(_depth + 1),
- default_state=state,
- default_state_factory=state_factory)
+ matcher = Matcher.new(
+ type,
+ Rule() & rule,
+ permission or Permission(),
+ temp=temp,
+ priority=priority,
+ block=block,
+ handlers=handlers,
+ plugin=_current_plugin.get(),
+ module=_get_matcher_module(_depth + 1),
+ default_state=state,
+ default_state_factory=state_factory,
+ )
_store_matcher(matcher)
return matcher
-def on_metaevent(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = None,
- temp: bool = False,
- priority: int = 1,
- block: bool = False,
- state: Optional[T_State] = None,
- state_factory: Optional[T_StateFactory] = None,
- _depth: int = 0) -> Type[Matcher]:
+def on_metaevent(
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = None,
+ temp: bool = False,
+ priority: int = 1,
+ block: bool = False,
+ state: Optional[T_State] = None,
+ state_factory: Optional[T_StateFactory] = None,
+ _depth: int = 0,
+) -> Type[Matcher]:
"""
:说明:
@@ -105,31 +121,35 @@ def on_metaevent(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- ``Type[Matcher]``
"""
- matcher = Matcher.new("meta_event",
- Rule() & rule,
- Permission(),
- temp=temp,
- priority=priority,
- block=block,
- handlers=handlers,
- plugin=_current_plugin.get(),
- module=_get_matcher_module(_depth + 1),
- default_state=state,
- default_state_factory=state_factory)
+ matcher = Matcher.new(
+ "meta_event",
+ Rule() & rule,
+ Permission(),
+ temp=temp,
+ priority=priority,
+ block=block,
+ handlers=handlers,
+ plugin=_current_plugin.get(),
+ module=_get_matcher_module(_depth + 1),
+ default_state=state,
+ default_state_factory=state_factory,
+ )
_store_matcher(matcher)
return matcher
-def on_message(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- permission: Optional[Permission] = None,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = None,
- temp: bool = False,
- priority: int = 1,
- block: bool = True,
- state: Optional[T_State] = None,
- state_factory: Optional[T_StateFactory] = None,
- _depth: int = 0) -> Type[Matcher]:
+def on_message(
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ permission: Optional[Permission] = None,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = None,
+ temp: bool = False,
+ priority: int = 1,
+ block: bool = True,
+ state: Optional[T_State] = None,
+ state_factory: Optional[T_StateFactory] = None,
+ _depth: int = 0,
+) -> Type[Matcher]:
"""
:说明:
@@ -150,30 +170,34 @@ def on_message(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- ``Type[Matcher]``
"""
- matcher = Matcher.new("message",
- Rule() & rule,
- permission or Permission(),
- temp=temp,
- priority=priority,
- block=block,
- handlers=handlers,
- plugin=_current_plugin.get(),
- module=_get_matcher_module(_depth + 1),
- default_state=state,
- default_state_factory=state_factory)
+ matcher = Matcher.new(
+ "message",
+ Rule() & rule,
+ permission or Permission(),
+ temp=temp,
+ priority=priority,
+ block=block,
+ handlers=handlers,
+ plugin=_current_plugin.get(),
+ module=_get_matcher_module(_depth + 1),
+ default_state=state,
+ default_state_factory=state_factory,
+ )
_store_matcher(matcher)
return matcher
-def on_notice(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = None,
- temp: bool = False,
- priority: int = 1,
- block: bool = False,
- state: Optional[T_State] = None,
- state_factory: Optional[T_StateFactory] = None,
- _depth: int = 0) -> Type[Matcher]:
+def on_notice(
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = None,
+ temp: bool = False,
+ priority: int = 1,
+ block: bool = False,
+ state: Optional[T_State] = None,
+ state_factory: Optional[T_StateFactory] = None,
+ _depth: int = 0,
+) -> Type[Matcher]:
"""
:说明:
@@ -193,30 +217,34 @@ def on_notice(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- ``Type[Matcher]``
"""
- matcher = Matcher.new("notice",
- Rule() & rule,
- Permission(),
- temp=temp,
- priority=priority,
- block=block,
- handlers=handlers,
- plugin=_current_plugin.get(),
- module=_get_matcher_module(_depth + 1),
- default_state=state,
- default_state_factory=state_factory)
+ matcher = Matcher.new(
+ "notice",
+ Rule() & rule,
+ Permission(),
+ temp=temp,
+ priority=priority,
+ block=block,
+ handlers=handlers,
+ plugin=_current_plugin.get(),
+ module=_get_matcher_module(_depth + 1),
+ default_state=state,
+ default_state_factory=state_factory,
+ )
_store_matcher(matcher)
return matcher
-def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = None,
- temp: bool = False,
- priority: int = 1,
- block: bool = False,
- state: Optional[T_State] = None,
- state_factory: Optional[T_StateFactory] = None,
- _depth: int = 0) -> Type[Matcher]:
+def on_request(
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = None,
+ temp: bool = False,
+ priority: int = 1,
+ block: bool = False,
+ state: Optional[T_State] = None,
+ state_factory: Optional[T_StateFactory] = None,
+ _depth: int = 0,
+) -> Type[Matcher]:
"""
:说明:
@@ -236,26 +264,30 @@ def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = None,
- ``Type[Matcher]``
"""
- matcher = Matcher.new("request",
- Rule() & rule,
- Permission(),
- temp=temp,
- priority=priority,
- block=block,
- handlers=handlers,
- plugin=_current_plugin.get(),
- module=_get_matcher_module(_depth + 1),
- default_state=state,
- default_state_factory=state_factory)
+ matcher = Matcher.new(
+ "request",
+ Rule() & rule,
+ Permission(),
+ temp=temp,
+ priority=priority,
+ block=block,
+ handlers=handlers,
+ plugin=_current_plugin.get(),
+ module=_get_matcher_module(_depth + 1),
+ default_state=state,
+ default_state_factory=state_factory,
+ )
_store_matcher(matcher)
return matcher
-def on_startswith(msg: Union[str, Tuple[str, ...]],
- rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
- ignorecase: bool = False,
- _depth: int = 0,
- **kwargs) -> Type[Matcher]:
+def on_startswith(
+ msg: Union[str, Tuple[str, ...]],
+ rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
+ ignorecase: bool = False,
+ _depth: int = 0,
+ **kwargs,
+) -> Type[Matcher]:
"""
:说明:
@@ -278,16 +310,16 @@ def on_startswith(msg: Union[str, Tuple[str, ...]],
- ``Type[Matcher]``
"""
- return on_message(startswith(msg, ignorecase) & rule,
- **kwargs,
- _depth=_depth + 1)
+ return on_message(startswith(msg, ignorecase) & rule, **kwargs, _depth=_depth + 1)
-def on_endswith(msg: Union[str, Tuple[str, ...]],
- rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
- ignorecase: bool = False,
- _depth: int = 0,
- **kwargs) -> Type[Matcher]:
+def on_endswith(
+ msg: Union[str, Tuple[str, ...]],
+ rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = None,
+ ignorecase: bool = False,
+ _depth: int = 0,
+ **kwargs,
+) -> Type[Matcher]:
"""
:说明:
@@ -310,15 +342,15 @@ def on_endswith(msg: Union[str, Tuple[str, ...]],
- ``Type[Matcher]``
"""
- return on_message(endswith(msg, ignorecase) & rule,
- **kwargs,
- _depth=_depth + 1)
+ return on_message(endswith(msg, ignorecase) & rule, **kwargs, _depth=_depth + 1)
-def on_keyword(keywords: Set[str],
- rule: Optional[Union[Rule, T_RuleChecker]] = None,
- _depth: int = 0,
- **kwargs) -> Type[Matcher]:
+def on_keyword(
+ keywords: Set[str],
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ _depth: int = 0,
+ **kwargs,
+) -> Type[Matcher]:
"""
:说明:
@@ -343,11 +375,13 @@ def on_keyword(keywords: Set[str],
return on_message(keyword(*keywords) & rule, **kwargs, _depth=_depth + 1)
-def on_command(cmd: Union[str, Tuple[str, ...]],
- rule: Optional[Union[Rule, T_RuleChecker]] = None,
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
- _depth: int = 0,
- **kwargs) -> Type[Matcher]:
+def on_command(
+ cmd: Union[str, Tuple[str, ...]],
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
+ _depth: int = 0,
+ **kwargs,
+) -> Type[Matcher]:
"""
:说明:
@@ -382,7 +416,8 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
if not segment_text.startswith(state[PREFIX_KEY][RAW_CMD_KEY]):
return
new_message = message.__class__(
- segment_text[len(state[PREFIX_KEY][RAW_CMD_KEY]):].lstrip())
+ segment_text[len(state[PREFIX_KEY][RAW_CMD_KEY]) :].lstrip()
+ )
for new_segment in reversed(new_message):
message.insert(0, new_segment)
@@ -390,18 +425,19 @@ def on_command(cmd: Union[str, Tuple[str, ...]],
handlers.insert(0, _strip_cmd)
commands = set([cmd]) | (aliases or set())
- return on_message(command(*commands) & rule,
- handlers=handlers,
- **kwargs,
- _depth=_depth + 1)
+ return on_message(
+ command(*commands) & rule, handlers=handlers, **kwargs, _depth=_depth + 1
+ )
-def on_shell_command(cmd: Union[str, Tuple[str, ...]],
- rule: Optional[Union[Rule, T_RuleChecker]] = None,
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
- parser: Optional[ArgumentParser] = None,
- _depth: int = 0,
- **kwargs) -> Type[Matcher]:
+def on_shell_command(
+ cmd: Union[str, Tuple[str, ...]],
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
+ parser: Optional[ArgumentParser] = None,
+ _depth: int = 0,
+ **kwargs,
+) -> Type[Matcher]:
"""
:说明:
@@ -434,7 +470,8 @@ def on_shell_command(cmd: Union[str, Tuple[str, ...]],
message = event.get_message()
segment = message.pop(0)
new_message = message.__class__(
- str(segment)[len(state[PREFIX_KEY][RAW_CMD_KEY]):].strip())
+ str(segment)[len(state[PREFIX_KEY][RAW_CMD_KEY]) :].strip()
+ )
for new_segment in reversed(new_message):
message.insert(0, new_segment)
@@ -442,17 +479,21 @@ def on_shell_command(cmd: Union[str, Tuple[str, ...]],
handlers.insert(0, _strip_cmd)
commands = set([cmd]) | (aliases or set())
- return on_message(shell_command(*commands, parser=parser) & rule,
- handlers=handlers,
- **kwargs,
- _depth=_depth + 1)
+ return on_message(
+ shell_command(*commands, parser=parser) & rule,
+ handlers=handlers,
+ **kwargs,
+ _depth=_depth + 1,
+ )
-def on_regex(pattern: str,
- flags: Union[int, re.RegexFlag] = 0,
- rule: Optional[Union[Rule, T_RuleChecker]] = None,
- _depth: int = 0,
- **kwargs) -> Type[Matcher]:
+def on_regex(
+ pattern: str,
+ flags: Union[int, re.RegexFlag] = 0,
+ rule: Optional[Union[Rule, T_RuleChecker]] = None,
+ _depth: int = 0,
+ **kwargs,
+) -> Type[Matcher]:
"""
:说明:
@@ -503,8 +544,7 @@ class CommandGroup:
- **说明**: 其他传递给 ``on_command`` 的参数默认值
"""
- def command(self, cmd: Union[str, Tuple[str, ...]],
- **kwargs) -> Type[Matcher]:
+ def command(self, cmd: Union[str, Tuple[str, ...]], **kwargs) -> Type[Matcher]:
"""
:说明:
@@ -526,8 +566,9 @@ class CommandGroup:
final_kwargs.update(kwargs)
return on_command(cmd, **final_kwargs, _depth=1)
- def shell_command(self, cmd: Union[str, Tuple[str, ...]],
- **kwargs) -> Type[Matcher]:
+ def shell_command(
+ self, cmd: Union[str, Tuple[str, ...]], **kwargs
+ ) -> Type[Matcher]:
"""
:说明:
@@ -708,8 +749,9 @@ class MatcherGroup:
self.matchers.append(matcher)
return matcher
- def on_startswith(self, msg: Union[str, Tuple[str, ...]],
- **kwargs) -> Type[Matcher]:
+ def on_startswith(
+ self, msg: Union[str, Tuple[str, ...]], **kwargs
+ ) -> Type[Matcher]:
"""
:说明:
@@ -739,8 +781,7 @@ class MatcherGroup:
self.matchers.append(matcher)
return matcher
- def on_endswith(self, msg: Union[str, Tuple[str, ...]],
- **kwargs) -> Type[Matcher]:
+ def on_endswith(self, msg: Union[str, Tuple[str, ...]], **kwargs) -> Type[Matcher]:
"""
:说明:
@@ -799,10 +840,12 @@ class MatcherGroup:
self.matchers.append(matcher)
return matcher
- def on_command(self,
- cmd: Union[str, Tuple[str, ...]],
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
- **kwargs) -> Type[Matcher]:
+ def on_command(
+ self,
+ cmd: Union[str, Tuple[str, ...]],
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
+ **kwargs,
+ ) -> Type[Matcher]:
"""
:说明:
@@ -834,12 +877,13 @@ class MatcherGroup:
self.matchers.append(matcher)
return matcher
- def on_shell_command(self,
- cmd: Union[str, Tuple[str, ...]],
- aliases: Optional[Set[Union[str, Tuple[str,
- ...]]]] = None,
- parser: Optional[ArgumentParser] = None,
- **kwargs) -> Type[Matcher]:
+ def on_shell_command(
+ self,
+ cmd: Union[str, Tuple[str, ...]],
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = None,
+ parser: Optional[ArgumentParser] = None,
+ **kwargs,
+ ) -> Type[Matcher]:
"""
:说明:
@@ -870,18 +914,15 @@ class MatcherGroup:
final_kwargs = self.base_kwargs.copy()
final_kwargs.update(kwargs)
final_kwargs.pop("type", None)
- matcher = on_shell_command(cmd,
- aliases=aliases,
- parser=parser,
- **final_kwargs,
- _depth=1)
+ matcher = on_shell_command(
+ cmd, aliases=aliases, parser=parser, **final_kwargs, _depth=1
+ )
self.matchers.append(matcher)
return matcher
- def on_regex(self,
- pattern: str,
- flags: Union[int, re.RegexFlag] = 0,
- **kwargs) -> Type[Matcher]:
+ def on_regex(
+ self, pattern: str, flags: Union[int, re.RegexFlag] = 0, **kwargs
+ ) -> Type[Matcher]:
"""
:说明:
diff --git a/nonebot/plugin/on.pyi b/nonebot/plugin/on.pyi
index 68e8ad62..affd285b 100644
--- a/nonebot/plugin/on.pyi
+++ b/nonebot/plugin/on.pyi
@@ -7,361 +7,335 @@ from nonebot.permission import Permission
from nonebot.rule import Rule, ArgumentParser
from nonebot.typing import T_State, T_Handler, T_RuleChecker, T_StateFactory
-
-def on(type: str = "",
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
+def on(
+ type: str = "",
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
def on_metaevent(
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_message(rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_notice(rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_request(rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- *,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_message(
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_notice(
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_request(
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ *,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
def on_startswith(
- msg: Union[str, Tuple[str, ...]],
- rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ...,
- ignorecase: bool = ...,
+ msg: Union[str, Tuple[str, ...]],
+ rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ...,
+ ignorecase: bool = ...,
+ *,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_endswith(
+ msg: Union[str, Tuple[str, ...]],
+ rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ...,
+ ignorecase: bool = ...,
+ *,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_keyword(
+ keywords: Set[str],
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ *,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_command(
+ cmd: Union[str, Tuple[str, ...]],
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
+ *,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_shell_command(
+ cmd: Union[str, Tuple[str, ...]],
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
+ parser: Optional[ArgumentParser] = ...,
+ *,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+def on_regex(
+ pattern: str,
+ flags: Union[int, re.RegexFlag] = ...,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ *,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+) -> Type[Matcher]: ...
+
+class CommandGroup:
+ def __init__(
+ self,
+ cmd: Union[str, Tuple[str, ...]],
*,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ...,
priority: int = ...,
block: bool = ...,
state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_endswith(msg: Union[str, Tuple[str, ...]],
- rule: Optional[Optional[Union[Rule, T_RuleChecker]]] = ...,
- ignorecase: bool = ...,
- *,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_keyword(keywords: Set[str],
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- *,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_command(cmd: Union[str, Tuple[str, ...]],
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
- *,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_shell_command(
+ state_factory: Optional[T_StateFactory] = ...,
+ ): ...
+ def command(
+ self,
cmd: Union[str, Tuple[str, ...]],
+ *,
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]],
rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def shell_command(
+ self,
+ cmd: Union[str, Tuple[str, ...]],
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]],
+ parser: Optional[ArgumentParser] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+
+class MatcherGroup:
+ def __init__(
+ self,
+ *,
+ type: str = ...,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ): ...
+ def on(
+ self,
+ *,
+ type: str = ...,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_metaevent(
+ self,
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_message(
+ self,
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_notice(
+ self,
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_request(
+ self,
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_startswith(
+ self,
+ msg: Union[str, Tuple[str, ...]],
+ *,
+ ignorecase: bool = ...,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_endswith(
+ self,
+ msg: Union[str, Tuple[str, ...]],
+ *,
+ ignorecase: bool = ...,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_keyword(
+ self,
+ keywords: Set[str],
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_command(
+ self,
+ cmd: Union[str, Tuple[str, ...]],
+ aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
+ def on_shell_command(
+ self,
+ cmd: Union[str, Tuple[str, ...]],
aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
parser: Optional[ArgumentParser] = ...,
*,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
permission: Optional[Permission] = ...,
handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
temp: bool = ...,
priority: int = ...,
block: bool = ...,
state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-def on_regex(pattern: str,
- flags: Union[int, re.RegexFlag] = ...,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- *,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-class CommandGroup:
-
- def __init__(self,
- cmd: Union[str, Tuple[str, ...]],
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...):
- ...
-
- def command(self,
- cmd: Union[str, Tuple[str, ...]],
- *,
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]],
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def shell_command(
- self,
- cmd: Union[str, Tuple[str, ...]],
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]],
- parser: Optional[ArgumentParser] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
-
-class MatcherGroup:
-
- def __init__(self,
- *,
- type: str = ...,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...):
- ...
-
- def on(self,
- *,
- type: str = ...,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_metaevent(
- self,
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_message(
- self,
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_notice(
- self,
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_request(
- self,
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_startswith(
- self,
- msg: Union[str, Tuple[str, ...]],
- *,
- ignorecase: bool = ...,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_endswith(
- self,
- msg: Union[str, Tuple[str, ...]],
- *,
- ignorecase: bool = ...,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_keyword(
- self,
- keywords: Set[str],
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_command(
- self,
- cmd: Union[str, Tuple[str, ...]],
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
- def on_shell_command(
- self,
- cmd: Union[str, Tuple[str, ...]],
- aliases: Optional[Set[Union[str, Tuple[str, ...]]]] = ...,
- parser: Optional[ArgumentParser] = ...,
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
-
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
def on_regex(
- self,
- pattern: str,
- flags: Union[int, re.RegexFlag] = ...,
- *,
- rule: Optional[Union[Rule, T_RuleChecker]] = ...,
- permission: Optional[Permission] = ...,
- handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
- temp: bool = ...,
- priority: int = ...,
- block: bool = ...,
- state: Optional[T_State] = ...,
- state_factory: Optional[T_StateFactory] = ...) -> Type[Matcher]:
- ...
+ self,
+ pattern: str,
+ flags: Union[int, re.RegexFlag] = ...,
+ *,
+ rule: Optional[Union[Rule, T_RuleChecker]] = ...,
+ permission: Optional[Permission] = ...,
+ handlers: Optional[List[Union[T_Handler, Handler]]] = ...,
+ temp: bool = ...,
+ priority: int = ...,
+ block: bool = ...,
+ state: Optional[T_State] = ...,
+ state_factory: Optional[T_StateFactory] = ...,
+ ) -> Type[Matcher]: ...
diff --git a/nonebot/plugin/plugin.py b/nonebot/plugin/plugin.py
index ee5a7c51..49e95dc2 100644
--- a/nonebot/plugin/plugin.py
+++ b/nonebot/plugin/plugin.py
@@ -15,6 +15,7 @@ plugins: Dict[str, "Plugin"] = {}
@dataclass(eq=False)
class Plugin(object):
"""存储插件信息"""
+
name: str
"""
- **类型**: ``str``
diff --git a/nonebot/plugins/echo.py b/nonebot/plugins/echo.py
index 763fd715..42e99cc3 100644
--- a/nonebot/plugins/echo.py
+++ b/nonebot/plugins/echo.py
@@ -3,15 +3,18 @@ from functools import reduce
from nonebot.rule import to_me
from nonebot.plugin import on_command
from nonebot.permission import SUPERUSER
-from nonebot.adapters.cqhttp import (Message, MessageEvent, MessageSegment,
- unescape)
+from nonebot.adapters.cqhttp import (
+ Message,
+ MessageEvent,
+ MessageSegment,
+ unescape,
+)
say = on_command("say", to_me(), permission=SUPERUSER)
@say.handle()
async def say_unescape(event: MessageEvent):
-
def _unescape(message: Message, segment: MessageSegment):
if segment.is_text():
return message.append(unescape(str(segment)))
diff --git a/nonebot/plugins/single_session.py b/nonebot/plugins/single_session.py
index 7bb4d52e..e76e1a1b 100644
--- a/nonebot/plugins/single_session.py
+++ b/nonebot/plugins/single_session.py
@@ -1,8 +1,11 @@
from typing import Dict
from nonebot.adapters import Event
-from nonebot.message import (IgnoredException, run_preprocessor,
- run_postprocessor)
+from nonebot.message import (
+ IgnoredException,
+ run_preprocessor,
+ run_postprocessor,
+)
_running_matcher: Dict[str, int] = {}
diff --git a/nonebot/rule.py b/nonebot/rule.py
index 2059ceac..e72cc372 100644
--- a/nonebot/rule.py
+++ b/nonebot/rule.py
@@ -17,8 +17,18 @@ from argparse import Namespace
from contextlib import AsyncExitStack
from typing_extensions import TypedDict
from argparse import ArgumentParser as ArgParser
-from typing import (Any, Dict, List, Type, Tuple, Union, Callable, NoReturn,
- Optional, Sequence)
+from typing import (
+ Any,
+ Dict,
+ List,
+ Type,
+ Tuple,
+ Union,
+ Callable,
+ NoReturn,
+ Optional,
+ Sequence,
+)
from pygtrie import CharTrie
@@ -33,10 +43,9 @@ PREFIX_KEY = "_prefix"
SUFFIX_KEY = "_suffix"
CMD_KEY = "command"
RAW_CMD_KEY = "raw_command"
-CMD_RESULT = TypedDict("CMD_RESULT", {
- "command": Optional[Tuple[str, ...]],
- "raw_command": Optional[str]
-})
+CMD_RESULT = TypedDict(
+ "CMD_RESULT", {"command": Optional[Tuple[str, ...]], "raw_command": Optional[str]}
+)
SHELL_ARGS = "_args"
SHELL_ARGV = "_argv"
@@ -61,11 +70,14 @@ class Rule:
from nonebot.utils import run_sync
Rule(async_function, run_sync(sync_function))
"""
+
__slots__ = ("checkers",)
HANDLER_PARAM_TYPES = [
- params.BotParam, params.EventParam, params.StateParam,
- params.DefaultParam
+ params.BotParam,
+ params.EventParam,
+ params.StateParam,
+ params.DefaultParam,
]
def __init__(self, *checkers: Union[T_RuleChecker, Handler]) -> None:
@@ -76,9 +88,11 @@ class Rule:
"""
self.checkers = set(
- checker if isinstance(checker, Handler) else Handler(
- checker, allow_types=self.HANDLER_PARAM_TYPES)
- for checker in checkers)
+ checker
+ if isinstance(checker, Handler)
+ else Handler(checker, allow_types=self.HANDLER_PARAM_TYPES)
+ for checker in checkers
+ )
"""
:说明:
@@ -95,8 +109,8 @@ class Rule:
event: Event,
state: T_State,
stack: Optional[AsyncExitStack] = None,
- dependency_cache: Optional[Dict[Callable[..., Any],
- Any]] = None) -> bool:
+ dependency_cache: Optional[Dict[Callable[..., Any], Any]] = None,
+ ) -> bool:
"""
:说明:
@@ -117,12 +131,17 @@ class Rule:
if not self.checkers:
return True
results = await asyncio.gather(
- *(checker(bot=bot,
- event=event,
- state=state,
- _stack=stack,
- _dependency_cache=dependency_cache)
- for checker in self.checkers))
+ *(
+ checker(
+ bot=bot,
+ event=event,
+ state=state,
+ _stack=stack,
+ _dependency_cache=dependency_cache,
+ )
+ for checker in self.checkers
+ )
+ )
return all(results)
def __and__(self, other: Optional[Union["Rule", T_RuleChecker]]) -> "Rule":
@@ -156,8 +175,9 @@ class TrieRule:
cls.suffix[suffix[::-1]] = value
@classmethod
- def get_value(cls, bot: Bot, event: Event,
- state: T_State) -> Tuple[CMD_RESULT, CMD_RESULT]:
+ def get_value(
+ cls, bot: Bot, event: Event, state: T_State
+ ) -> Tuple[CMD_RESULT, CMD_RESULT]:
prefix = CMD_RESULT(command=None, raw_command=None)
suffix = CMD_RESULT(command=None, raw_command=None)
state[PREFIX_KEY] = prefix
@@ -180,8 +200,7 @@ class TrieRule:
return prefix, suffix
-def startswith(msg: Union[str, Tuple[str, ...]],
- ignorecase: bool = False) -> Rule:
+def startswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule:
"""
:说明:
@@ -196,7 +215,8 @@ def startswith(msg: Union[str, Tuple[str, ...]],
pattern = re.compile(
f"^(?:{'|'.join(re.escape(prefix) for prefix in msg)})",
- re.IGNORECASE if ignorecase else 0)
+ re.IGNORECASE if ignorecase else 0,
+ )
async def _startswith(bot: Bot, event: Event, state: T_State) -> bool:
if event.get_type() != "message":
@@ -207,8 +227,7 @@ def startswith(msg: Union[str, Tuple[str, ...]],
return Rule(_startswith)
-def endswith(msg: Union[str, Tuple[str, ...]],
- ignorecase: bool = False) -> Rule:
+def endswith(msg: Union[str, Tuple[str, ...]], ignorecase: bool = False) -> Rule:
"""
:说明:
@@ -223,7 +242,8 @@ def endswith(msg: Union[str, Tuple[str, ...]],
pattern = re.compile(
f"(?:{'|'.join(re.escape(prefix) for prefix in msg)})$",
- re.IGNORECASE if ignorecase else 0)
+ re.IGNORECASE if ignorecase else 0,
+ )
async def _endswith(bot: Bot, event: Event, state: T_State) -> bool:
if event.get_type() != "message":
@@ -314,19 +334,22 @@ class ArgumentParser(ArgParser):
setattr(self, "message", old_message)
def exit(self, status: int = 0, message: Optional[str] = None):
- raise ParserExit(status=status,
- message=message or getattr(self, "message", None))
+ raise ParserExit(
+ status=status, message=message or getattr(self, "message", None)
+ )
- def parse_args(self,
- args: Optional[Sequence[str]] = None,
- namespace: Optional[Namespace] = None) -> Namespace:
+ def parse_args(
+ self,
+ args: Optional[Sequence[str]] = None,
+ namespace: Optional[Namespace] = None,
+ ) -> Namespace:
setattr(self, "message", "")
- return super().parse_args(args=args,
- namespace=namespace) # type: ignore
+ return super().parse_args(args=args, namespace=namespace) # type: ignore
-def shell_command(*cmds: Union[str, Tuple[str, ...]],
- parser: Optional[ArgumentParser] = None) -> Rule:
+def shell_command(
+ *cmds: Union[str, Tuple[str, ...]], parser: Optional[ArgumentParser] = None
+) -> Rule:
r"""
:说明:
@@ -361,8 +384,7 @@ def shell_command(*cmds: Union[str, Tuple[str, ...]],
\:\:\:
"""
if not isinstance(parser, ArgumentParser):
- raise TypeError(
- "`parser` must be an instance of nonebot.rule.ArgumentParser")
+ raise TypeError("`parser` must be an instance of nonebot.rule.ArgumentParser")
config = get_driver().config
command_start = config.command_start
@@ -382,8 +404,7 @@ def shell_command(*cmds: Union[str, Tuple[str, ...]],
async def _shell_command(event: Event, state: T_State) -> bool:
if state[PREFIX_KEY][CMD_KEY] in commands:
message = str(event.get_message())
- strip_message = message[len(state[PREFIX_KEY][RAW_CMD_KEY]
- ):].lstrip()
+ strip_message = message[len(state[PREFIX_KEY][RAW_CMD_KEY]) :].lstrip()
state[SHELL_ARGV] = shlex.split(strip_message)
if parser:
try:
diff --git a/nonebot/typing.py b/nonebot/typing.py
index 3394cd6f..04632c72 100644
--- a/nonebot/typing.py
+++ b/nonebot/typing.py
@@ -18,8 +18,17 @@
https://docs.python.org/3/library/typing.html
"""
-from typing import (TYPE_CHECKING, Any, Dict, Union, TypeVar, Callable,
- NoReturn, Optional, Awaitable)
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Dict,
+ Union,
+ TypeVar,
+ Callable,
+ NoReturn,
+ Optional,
+ Awaitable,
+)
if TYPE_CHECKING:
from nonebot.adapters import Bot, Event
@@ -29,10 +38,8 @@ T_Wrapped = TypeVar("T_Wrapped", bound=Callable)
def overrides(InterfaceClass: object):
-
def overrider(func: T_Wrapped) -> T_Wrapped:
- assert func.__name__ in dir(
- InterfaceClass), f"Error method: {func.__name__}"
+ assert func.__name__ in dir(InterfaceClass), f"Error method: {func.__name__}"
return func
return overrider
@@ -80,7 +87,8 @@ T_CallingAPIHook = Callable[["Bot", str, Dict[str, Any]], Awaitable[None]]
``bot.call_api`` 时执行的函数
"""
T_CalledAPIHook = Callable[
- ["Bot", Optional[Exception], str, Dict[str, Any], Any], Awaitable[None]]
+ ["Bot", Optional[Exception], str, Dict[str, Any], Any], Awaitable[None]
+]
"""
:类型: ``Callable[[Bot, Optional[Exception], str, Dict[str, Any], Any], Awaitable[None]]``
@@ -193,8 +201,9 @@ T_DependencyCache = Dict[T_Handler, Any]
依赖缓存, 用于存储依赖函数的返回值
"""
-T_ArgsParser = Callable[["Bot", "Event", T_State], Union[Awaitable[None],
- Awaitable[NoReturn]]]
+T_ArgsParser = Callable[
+ ["Bot", "Event", T_State], Union[Awaitable[None], Awaitable[NoReturn]]
+]
"""
:类型: ``Callable[[Bot, Event, T_State], Union[Awaitable[None], Awaitable[NoReturn]]]``
@@ -210,8 +219,9 @@ T_TypeUpdater = Callable[["Bot", "Event", T_State, str], Awaitable[str]]
TypeUpdater 在 Matcher.pause, Matcher.reject 时被运行,用于更新响应的事件类型。默认会更新为 ``message``。
"""
-T_PermissionUpdater = Callable[["Bot", "Event", T_State, "Permission"],
- Awaitable["Permission"]]
+T_PermissionUpdater = Callable[
+ ["Bot", "Event", T_State, "Permission"], Awaitable["Permission"]
+]
"""
:类型: ``Callable[[Bot, Event, T_State, Permission], Awaitable[Permission]]``
diff --git a/nonebot/utils.py b/nonebot/utils.py
index 32eca0db..001ee43e 100644
--- a/nonebot/utils.py
+++ b/nonebot/utils.py
@@ -8,8 +8,19 @@ from functools import wraps, partial
from contextlib import asynccontextmanager
from typing_extensions import GenericAlias # type: ignore
from typing_extensions import ParamSpec, get_args, get_origin
-from typing import (Any, Type, Deque, Tuple, Union, TypeVar, Callable, Optional,
- Awaitable, AsyncGenerator, ContextManager)
+from typing import (
+ Any,
+ Type,
+ Deque,
+ Tuple,
+ Union,
+ TypeVar,
+ Callable,
+ Optional,
+ Awaitable,
+ AsyncGenerator,
+ ContextManager,
+)
from nonebot.log import logger
from nonebot.typing import overrides
@@ -37,15 +48,16 @@ def escape_tag(s: str) -> str:
def generic_check_issubclass(
- cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any],
- ...]]) -> bool:
+ cls: Any, class_or_tuple: Union[Type[Any], Tuple[Type[Any], ...]]
+) -> bool:
try:
return issubclass(cls, class_or_tuple)
except TypeError:
if get_origin(cls) is Union:
for type_ in get_args(cls):
if type_ is not type(None) and not generic_check_issubclass(
- type_, class_or_tuple):
+ type_, class_or_tuple
+ ):
return False
return True
elif isinstance(cls, GenericAlias):
@@ -104,7 +116,8 @@ def run_sync(func: Callable[P, R]) -> Callable[P, Awaitable[R]]:
@asynccontextmanager
async def run_sync_ctx_manager(
- cm: ContextManager[T],) -> AsyncGenerator[T, None]:
+ cm: ContextManager[T],
+) -> AsyncGenerator[T, None]:
try:
yield await run_sync(cm.__enter__)()
except Exception as e:
@@ -122,7 +135,6 @@ def get_name(obj: Any) -> str:
class CacheLock:
-
def __init__(self):
self._waiters: Optional[Deque[asyncio.Future]] = None
self._locked = False
@@ -144,8 +156,9 @@ class CacheLock:
return self._locked
async def acquire(self):
- if (not self._locked and (self._waiters is None or
- all(w.cancelled() for w in self._waiters))):
+ if not self._locked and (
+ self._waiters is None or all(w.cancelled() for w in self._waiters)
+ ):
self._locked = True
return True
@@ -223,6 +236,7 @@ def logger_wrapper(logger_name: str):
def log(level: str, message: str, exception: Optional[Exception] = None):
return logger.opt(colors=True, exception=exception).log(
- level, f"{escape_tag(logger_name)} | " + message)
+ level, f"{escape_tag(logger_name)} | " + message
+ )
return log
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py
index 554e1209..be88edce 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py
@@ -12,8 +12,15 @@ from nonebot.typing import overrides
from nonebot.message import handle_event
from nonebot.adapters import Bot as BaseBot
from nonebot.utils import DataclassEncoder, escape_tag
-from nonebot.drivers import (Driver, WebSocket, HTTPRequest, HTTPResponse,
- ForwardDriver, HTTPConnection, WebSocketSetup)
+from nonebot.drivers import (
+ Driver,
+ WebSocket,
+ HTTPRequest,
+ HTTPResponse,
+ ForwardDriver,
+ HTTPConnection,
+ WebSocketSetup,
+)
from .utils import log, escape
from .config import Config as CQHTTPConfig
@@ -49,15 +56,12 @@ async def _check_reply(bot: "Bot", event: "Event"):
return
try:
- index = list(map(lambda x: x.type == "reply",
- event.message)).index(True)
+ index = list(map(lambda x: x.type == "reply", event.message)).index(True)
except ValueError:
return
msg_seg = event.message[index]
try:
- event.reply = Reply.parse_obj(await
- bot.get_msg(message_id=msg_seg.data["id"]
- ))
+ event.reply = Reply.parse_obj(await bot.get_msg(message_id=msg_seg.data["id"]))
except Exception as e:
log("WARNING", f"Error when getting message reply info: {repr(e)}", e)
return
@@ -68,8 +72,7 @@ async def _check_reply(bot: "Bot", event: "Event"):
if len(event.message) > index and event.message[index].type == "at":
del event.message[index]
if len(event.message) > index and event.message[index].type == "text":
- event.message[index].data["text"] = event.message[index].data[
- "text"].lstrip()
+ event.message[index].data["text"] = event.message[index].data["text"].lstrip()
if not event.message[index].data["text"]:
del event.message[index]
if not event.message:
@@ -99,23 +102,24 @@ def _check_at_me(bot: "Bot", event: "Event"):
else:
def _is_at_me_seg(segment: MessageSegment):
- return segment.type == "at" and str(segment.data.get(
- "qq", "")) == str(event.self_id)
+ return segment.type == "at" and str(segment.data.get("qq", "")) == str(
+ event.self_id
+ )
# check the first segment
if _is_at_me_seg(event.message[0]):
event.to_me = True
event.message.pop(0)
if event.message and event.message[0].type == "text":
- event.message[0].data["text"] = event.message[0].data[
- "text"].lstrip()
+ event.message[0].data["text"] = event.message[0].data["text"].lstrip()
if not event.message[0].data["text"]:
del event.message[0]
if event.message and _is_at_me_seg(event.message[0]):
event.message.pop(0)
if event.message and event.message[0].type == "text":
- event.message[0].data["text"] = event.message[0].data[
- "text"].lstrip()
+ event.message[0].data["text"] = (
+ event.message[0].data["text"].lstrip()
+ )
if not event.message[0].data["text"]:
del event.message[0]
@@ -123,9 +127,11 @@ def _check_at_me(bot: "Bot", event: "Event"):
# check the last segment
i = -1
last_msg_seg = event.message[i]
- if last_msg_seg.type == "text" and \
- not last_msg_seg.data["text"].strip() and \
- len(event.message) >= 2:
+ if (
+ last_msg_seg.type == "text"
+ and not last_msg_seg.data["text"].strip()
+ and len(event.message) >= 2
+ ):
i -= 1
last_msg_seg = event.message[i]
@@ -161,13 +167,12 @@ def _check_nickname(bot: "Bot", event: "Event"):
if nicknames:
# check if the user is calling me with my nickname
nickname_regex = "|".join(nicknames)
- m = re.search(rf"^({nickname_regex})([\s,,]*|$)", first_text,
- re.IGNORECASE)
+ m = re.search(rf"^({nickname_regex})([\s,,]*|$)", first_text, re.IGNORECASE)
if m:
nickname = m.group(1)
log("DEBUG", f"User is calling me {nickname}")
event.to_me = True
- first_msg_seg.data["text"] = first_text[m.end():]
+ first_msg_seg.data["text"] = first_text[m.end() :]
def _handle_api_result(result: Optional[Dict[str, Any]]) -> Any:
@@ -206,8 +211,9 @@ class ResultStore:
@classmethod
def add_result(cls, result: Dict[str, Any]):
- if isinstance(result.get("echo"), dict) and \
- isinstance(result["echo"].get("seq"), int):
+ if isinstance(result.get("echo"), dict) and isinstance(
+ result["echo"].get("seq"), int
+ ):
future = cls._futures.get(result["echo"]["seq"])
if future:
future.set_result(result)
@@ -228,6 +234,7 @@ class Bot(BaseBot):
"""
CQHTTP 协议 Bot 适配。继承属性参考 `BaseBot <./#class-basebot>`_ 。
"""
+
cqhttp_config: CQHTTPConfig
@property
@@ -249,22 +256,25 @@ class Bot(BaseBot):
elif isinstance(driver, ForwardDriver) and cls.cqhttp_config.ws_urls:
for self_id, url in cls.cqhttp_config.ws_urls.items():
try:
- headers = {
- "authorization":
- f"Bearer {cls.cqhttp_config.access_token}"
- } if cls.cqhttp_config.access_token else {}
+ headers = (
+ {"authorization": f"Bearer {cls.cqhttp_config.access_token}"}
+ if cls.cqhttp_config.access_token
+ else {}
+ )
driver.setup_websocket(
- WebSocketSetup("cqhttp", self_id, url, headers=headers))
+ WebSocketSetup("cqhttp", self_id, url, headers=headers)
+ )
except Exception as e:
logger.opt(colors=True, exception=e).error(
f"Bad url {escape_tag(url)} for bot {escape_tag(self_id)} "
- "in cqhttp forward websocket")
+ "in cqhttp forward websocket"
+ )
@classmethod
@overrides(BaseBot)
async def check_permission(
- cls, driver: Driver,
- request: HTTPConnection) -> Tuple[Optional[str], HTTPResponse]:
+ cls, driver: Driver, request: HTTPConnection
+ ) -> Tuple[Optional[str], HTTPResponse]:
"""
:说明:
@@ -286,22 +296,26 @@ class Bot(BaseBot):
if not x_signature:
log("WARNING", "Missing Signature Header")
return None, HTTPResponse(401, b"Missing Signature")
- sig = hmac.new(secret.encode("utf-8"), request.body,
- "sha1").hexdigest()
+ sig = hmac.new(secret.encode("utf-8"), request.body, "sha1").hexdigest()
if x_signature != "sha1=" + sig:
log("WARNING", "Signature Header is invalid")
return None, HTTPResponse(403, b"Signature is invalid")
access_token = cqhttp_config.access_token
- if access_token and access_token != token and isinstance(
- request, WebSocket):
+ if access_token and access_token != token and isinstance(request, WebSocket):
log(
- "WARNING", "Authorization Header is invalid"
- if token else "Missing Authorization Header")
+ "WARNING",
+ "Authorization Header is invalid"
+ if token
+ else "Missing Authorization Header",
+ )
return None, HTTPResponse(
- 403, b"Authorization Header is invalid"
- if token else b"Missing Authorization Header")
- return str(x_self_id), HTTPResponse(204, b'')
+ 403,
+ b"Authorization Header is invalid"
+ if token
+ else b"Missing Authorization Header",
+ )
+ return str(x_self_id), HTTPResponse(204, b"")
@overrides(BaseBot)
async def handle_message(self, message: bytes):
@@ -320,7 +334,7 @@ class Bot(BaseBot):
return
try:
- post_type = data['post_type']
+ post_type = data["post_type"]
detail_type = data.get(f"{post_type}_type")
detail_type = f".{detail_type}" if detail_type else ""
sub_type = data.get("sub_type")
@@ -352,17 +366,13 @@ class Bot(BaseBot):
if isinstance(self.request, WebSocket):
seq = ResultStore.get_seq()
json_data = json.dumps(
- {
- "action": api,
- "params": data,
- "echo": {
- "seq": seq
- }
- },
- cls=DataclassEncoder)
+ {"action": api, "params": data, "echo": {"seq": seq}},
+ cls=DataclassEncoder,
+ )
await self.request.send(json_data)
- return _handle_api_result(await ResultStore.fetch(
- seq, self.config.api_timeout))
+ return _handle_api_result(
+ await ResultStore.fetch(seq, self.config.api_timeout)
+ )
elif isinstance(self.request, HTTPRequest):
api_root = self.config.api_root.get(self.self_id)
@@ -373,22 +383,25 @@ class Bot(BaseBot):
headers = {"Content-Type": "application/json"}
if self.cqhttp_config.access_token is not None:
- headers[
- "Authorization"] = "Bearer " + self.cqhttp_config.access_token
+ headers["Authorization"] = "Bearer " + self.cqhttp_config.access_token
try:
- async with httpx.AsyncClient(headers=headers,
- follow_redirects=True) as client:
+ async with httpx.AsyncClient(
+ headers=headers, follow_redirects=True
+ ) as client:
response = await client.post(
api_root + api,
content=json.dumps(data, cls=DataclassEncoder),
- timeout=self.config.api_timeout)
+ timeout=self.config.api_timeout,
+ )
if 200 <= response.status_code < 300:
result = response.json()
return _handle_api_result(result)
- raise NetworkError(f"HTTP request received unexpected "
- f"status code: {response.status_code}")
+ raise NetworkError(
+ f"HTTP request received unexpected "
+ f"status code: {response.status_code}"
+ )
except httpx.InvalidURL:
raise NetworkError("API root url invalid")
except httpx.HTTPError:
@@ -418,11 +431,13 @@ class Bot(BaseBot):
return await super().call_api(api, **data)
@overrides(BaseBot)
- async def send(self,
- event: Event,
- message: Union[str, Message, MessageSegment],
- at_sender: bool = False,
- **kwargs) -> Any:
+ async def send(
+ self,
+ event: Event,
+ message: Union[str, Message, MessageSegment],
+ at_sender: bool = False,
+ **kwargs,
+ ) -> Any:
"""
:说明:
@@ -445,8 +460,9 @@ class Bot(BaseBot):
- ``NetworkError``: 网络错误
- ``ActionFailed``: API 调用失败
"""
- message = escape(message, escape_comma=False) if isinstance(
- message, str) else message
+ message = (
+ escape(message, escape_comma=False) if isinstance(message, str) else message
+ )
msg = message if isinstance(message, Message) else Message(message)
at_sender = at_sender and bool(getattr(event, "user_id", None))
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.pyi b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.pyi
index 8152bb6f..39ad4122 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.pyi
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.pyi
@@ -8,7 +8,6 @@ from nonebot.drivers import Driver, WebSocket
from .event import Event
from .message import Message, MessageSegment
-
def get_auth_bearer(access_token: Optional[str] = ...) -> Optional[str]:
...
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/config.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/config.py
index ee894893..12908073 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/config.py
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/config.py
@@ -1,6 +1,6 @@
from typing import Dict, Optional
-from pydantic import Field, BaseModel, AnyUrl
+from pydantic import Field, AnyUrl, BaseModel
# priority: alias > origin
@@ -14,11 +14,10 @@ class Config(BaseModel):
- ``secret`` / ``cqhttp_secret``: CQHTTP HTTP 上报数据签名口令
- ``ws_urls`` / ``cqhttp_ws_urls``: CQHTTP 正向 Websocket 连接 Bot ID、目标 URL 字典
"""
- access_token: Optional[str] = Field(default=None,
- alias="cqhttp_access_token")
+
+ access_token: Optional[str] = Field(default=None, alias="cqhttp_access_token")
secret: Optional[str] = Field(default=None, alias="cqhttp_secret")
- ws_urls: Dict[str, AnyUrl] = Field(default_factory=set,
- alias="cqhttp_ws_urls")
+ ws_urls: Dict[str, AnyUrl] = Field(default_factory=set, alias="cqhttp_ws_urls")
class Config:
extra = "ignore"
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/event.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/event.py
index 690a8437..21c7b34c 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/event.py
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/event.py
@@ -5,12 +5,13 @@ from typing import TYPE_CHECKING, List, Type, Optional
from pydantic import BaseModel
from pygtrie import StringTrie
-from .message import Message
from nonebot.typing import overrides
from nonebot.utils import escape_tag
-from .exception import NoLogException
from nonebot.adapters import Event as BaseEvent
+from .message import Message
+from .exception import NoLogException
+
if TYPE_CHECKING:
from .bot import Bot
@@ -22,6 +23,7 @@ class Event(BaseEvent):
.. _CQHTTP 文档:
https://github.com/howmanybots/onebot/blob/master/README.md
"""
+
__event__ = ""
time: int
self_id: int
@@ -118,6 +120,7 @@ class Status(BaseModel):
# Message Events
class MessageEvent(Event):
"""消息事件"""
+
__event__ = "message"
post_type: Literal["message"]
sub_type: str
@@ -144,8 +147,9 @@ class MessageEvent(Event):
@overrides(Event)
def get_event_name(self) -> str:
sub_type = getattr(self, "sub_type", None)
- return f"{self.post_type}.{self.message_type}" + (f".{sub_type}"
- if sub_type else "")
+ return f"{self.post_type}.{self.message_type}" + (
+ f".{sub_type}" if sub_type else ""
+ )
@overrides(Event)
def get_message(self) -> Message:
@@ -170,20 +174,29 @@ class MessageEvent(Event):
class PrivateMessageEvent(MessageEvent):
"""私聊消息"""
+
__event__ = "message.private"
message_type: Literal["private"]
@overrides(Event)
def get_event_description(self) -> str:
- return (f'Message {self.message_id} from {self.user_id} "' + "".join(
- map(
- lambda x: escape_tag(str(x))
- if x.is_text() else f"{escape_tag(str(x))}",
- self.message)) + '"')
+ return (
+ f'Message {self.message_id} from {self.user_id} "'
+ + "".join(
+ map(
+ lambda x: escape_tag(str(x))
+ if x.is_text()
+ else f"{escape_tag(str(x))}",
+ self.message,
+ )
+ )
+ + '"'
+ )
class GroupMessageEvent(MessageEvent):
"""群消息"""
+
__event__ = "message.group"
message_type: Literal["group"]
group_id: int
@@ -196,8 +209,13 @@ class GroupMessageEvent(MessageEvent):
+ "".join(
map(
lambda x: escape_tag(str(x))
- if x.is_text() else f"{escape_tag(str(x))}",
- self.message)) + '"')
+ if x.is_text()
+ else f"{escape_tag(str(x))}",
+ self.message,
+ )
+ )
+ + '"'
+ )
@overrides(MessageEvent)
def get_session_id(self) -> str:
@@ -207,6 +225,7 @@ class GroupMessageEvent(MessageEvent):
# Notice Events
class NoticeEvent(Event):
"""通知事件"""
+
__event__ = "notice"
post_type: Literal["notice"]
notice_type: str
@@ -214,12 +233,14 @@ class NoticeEvent(Event):
@overrides(Event)
def get_event_name(self) -> str:
sub_type = getattr(self, "sub_type", None)
- return f"{self.post_type}.{self.notice_type}" + (f".{sub_type}"
- if sub_type else "")
+ return f"{self.post_type}.{self.notice_type}" + (
+ f".{sub_type}" if sub_type else ""
+ )
class GroupUploadNoticeEvent(NoticeEvent):
"""群文件上传事件"""
+
__event__ = "notice.group_upload"
notice_type: Literal["group_upload"]
user_id: int
@@ -237,6 +258,7 @@ class GroupUploadNoticeEvent(NoticeEvent):
class GroupAdminNoticeEvent(NoticeEvent):
"""群管理员变动"""
+
__event__ = "notice.group_admin"
notice_type: Literal["group_admin"]
sub_type: str
@@ -258,6 +280,7 @@ class GroupAdminNoticeEvent(NoticeEvent):
class GroupDecreaseNoticeEvent(NoticeEvent):
"""群成员减少事件"""
+
__event__ = "notice.group_decrease"
notice_type: Literal["group_decrease"]
sub_type: str
@@ -280,6 +303,7 @@ class GroupDecreaseNoticeEvent(NoticeEvent):
class GroupIncreaseNoticeEvent(NoticeEvent):
"""群成员增加事件"""
+
__event__ = "notice.group_increase"
notice_type: Literal["group_increase"]
sub_type: str
@@ -302,6 +326,7 @@ class GroupIncreaseNoticeEvent(NoticeEvent):
class GroupBanNoticeEvent(NoticeEvent):
"""群禁言事件"""
+
__event__ = "notice.group_ban"
notice_type: Literal["group_ban"]
sub_type: str
@@ -325,6 +350,7 @@ class GroupBanNoticeEvent(NoticeEvent):
class FriendAddNoticeEvent(NoticeEvent):
"""好友添加事件"""
+
__event__ = "notice.friend_add"
notice_type: Literal["friend_add"]
user_id: int
@@ -340,6 +366,7 @@ class FriendAddNoticeEvent(NoticeEvent):
class GroupRecallNoticeEvent(NoticeEvent):
"""群消息撤回事件"""
+
__event__ = "notice.group_recall"
notice_type: Literal["group_recall"]
user_id: int
@@ -362,6 +389,7 @@ class GroupRecallNoticeEvent(NoticeEvent):
class FriendRecallNoticeEvent(NoticeEvent):
"""好友消息撤回事件"""
+
__event__ = "notice.friend_recall"
notice_type: Literal["friend_recall"]
user_id: int
@@ -378,6 +406,7 @@ class FriendRecallNoticeEvent(NoticeEvent):
class NotifyEvent(NoticeEvent):
"""提醒事件"""
+
__event__ = "notice.notify"
notice_type: Literal["notify"]
sub_type: str
@@ -395,6 +424,7 @@ class NotifyEvent(NoticeEvent):
class PokeNotifyEvent(NotifyEvent):
"""戳一戳提醒事件"""
+
__event__ = "notice.notify.poke"
sub_type: Literal["poke"]
target_id: int
@@ -413,6 +443,7 @@ class PokeNotifyEvent(NotifyEvent):
class LuckyKingNotifyEvent(NotifyEvent):
"""群红包运气王提醒事件"""
+
__event__ = "notice.notify.lucky_king"
sub_type: Literal["lucky_king"]
target_id: int
@@ -432,6 +463,7 @@ class LuckyKingNotifyEvent(NotifyEvent):
class HonorNotifyEvent(NotifyEvent):
"""群荣誉变更提醒事件"""
+
__event__ = "notice.notify.honor"
sub_type: Literal["honor"]
honor_type: str
@@ -444,6 +476,7 @@ class HonorNotifyEvent(NotifyEvent):
# Request Events
class RequestEvent(Event):
"""请求事件"""
+
__event__ = "request"
post_type: Literal["request"]
request_type: str
@@ -451,12 +484,14 @@ class RequestEvent(Event):
@overrides(Event)
def get_event_name(self) -> str:
sub_type = getattr(self, "sub_type", None)
- return f"{self.post_type}.{self.request_type}" + (f".{sub_type}"
- if sub_type else "")
+ return f"{self.post_type}.{self.request_type}" + (
+ f".{sub_type}" if sub_type else ""
+ )
class FriendRequestEvent(RequestEvent):
"""加好友请求事件"""
+
__event__ = "request.friend"
request_type: Literal["friend"]
user_id: int
@@ -472,9 +507,9 @@ class FriendRequestEvent(RequestEvent):
return str(self.user_id)
async def approve(self, bot: "Bot", remark: str = ""):
- return await bot.set_friend_add_request(flag=self.flag,
- approve=True,
- remark=remark)
+ return await bot.set_friend_add_request(
+ flag=self.flag, approve=True, remark=remark
+ )
async def reject(self, bot: "Bot"):
return await bot.set_friend_add_request(flag=self.flag, approve=False)
@@ -482,6 +517,7 @@ class FriendRequestEvent(RequestEvent):
class GroupRequestEvent(RequestEvent):
"""加群请求/邀请事件"""
+
__event__ = "request.group"
request_type: Literal["group"]
sub_type: str
@@ -499,20 +535,20 @@ class GroupRequestEvent(RequestEvent):
return f"group_{self.group_id}_{self.user_id}"
async def approve(self, bot: "Bot"):
- return await bot.set_group_add_request(flag=self.flag,
- sub_type=self.sub_type,
- approve=True)
+ return await bot.set_group_add_request(
+ flag=self.flag, sub_type=self.sub_type, approve=True
+ )
async def reject(self, bot: "Bot", reason: str = ""):
- return await bot.set_group_add_request(flag=self.flag,
- sub_type=self.sub_type,
- approve=False,
- reason=reason)
+ return await bot.set_group_add_request(
+ flag=self.flag, sub_type=self.sub_type, approve=False, reason=reason
+ )
# Meta Events
class MetaEvent(Event):
"""元事件"""
+
__event__ = "meta_event"
post_type: Literal["meta_event"]
meta_event_type: str
@@ -520,8 +556,9 @@ class MetaEvent(Event):
@overrides(Event)
def get_event_name(self) -> str:
sub_type = getattr(self, "sub_type", None)
- return f"{self.post_type}.{self.meta_event_type}" + (f".{sub_type}" if
- sub_type else "")
+ return f"{self.post_type}.{self.meta_event_type}" + (
+ f".{sub_type}" if sub_type else ""
+ )
@overrides(Event)
def get_log_string(self) -> str:
@@ -530,6 +567,7 @@ class MetaEvent(Event):
class LifecycleMetaEvent(MetaEvent):
"""生命周期元事件"""
+
__event__ = "meta_event.lifecycle"
meta_event_type: Literal["lifecycle"]
sub_type: str
@@ -537,6 +575,7 @@ class LifecycleMetaEvent(MetaEvent):
class HeartbeatMetaEvent(MetaEvent):
"""心跳元事件"""
+
__event__ = "meta_event.heartbeat"
meta_event_type: Literal["heartbeat"]
status: Status
@@ -567,12 +606,28 @@ def get_event_model(event_name) -> List[Type[Event]]:
__all__ = [
- "Event", "MessageEvent", "PrivateMessageEvent", "GroupMessageEvent",
- "NoticeEvent", "GroupUploadNoticeEvent", "GroupAdminNoticeEvent",
- "GroupDecreaseNoticeEvent", "GroupIncreaseNoticeEvent",
- "GroupBanNoticeEvent", "FriendAddNoticeEvent", "GroupRecallNoticeEvent",
- "FriendRecallNoticeEvent", "NotifyEvent", "PokeNotifyEvent",
- "LuckyKingNotifyEvent", "HonorNotifyEvent", "RequestEvent",
- "FriendRequestEvent", "GroupRequestEvent", "MetaEvent",
- "LifecycleMetaEvent", "HeartbeatMetaEvent", "get_event_model"
+ "Event",
+ "MessageEvent",
+ "PrivateMessageEvent",
+ "GroupMessageEvent",
+ "NoticeEvent",
+ "GroupUploadNoticeEvent",
+ "GroupAdminNoticeEvent",
+ "GroupDecreaseNoticeEvent",
+ "GroupIncreaseNoticeEvent",
+ "GroupBanNoticeEvent",
+ "FriendAddNoticeEvent",
+ "GroupRecallNoticeEvent",
+ "FriendRecallNoticeEvent",
+ "NotifyEvent",
+ "PokeNotifyEvent",
+ "LuckyKingNotifyEvent",
+ "HonorNotifyEvent",
+ "RequestEvent",
+ "FriendRequestEvent",
+ "GroupRequestEvent",
+ "MetaEvent",
+ "LifecycleMetaEvent",
+ "HeartbeatMetaEvent",
+ "get_event_model",
]
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/exception.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/exception.py
index 4d3fd1e9..1ea01f80 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/exception.py
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/exception.py
@@ -8,7 +8,6 @@ from nonebot.exception import ApiNotAvailable as BaseApiNotAvailable
class CQHTTPAdapterException(AdapterException):
-
def __init__(self):
super().__init__("cqhttp")
@@ -33,8 +32,11 @@ class ActionFailed(BaseActionFailed, CQHTTPAdapterException):
self.info = kwargs
def __repr__(self):
- return f""
+ return (
+ f""
+ )
def __str__(self):
return self.__repr__()
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/message.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/message.py
index 37db4e88..8ca6378a 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/message.py
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/message.py
@@ -5,10 +5,11 @@ from base64 import b64encode
from typing import Any, Type, Tuple, Union, Mapping, Iterable, Optional, cast
from nonebot.typing import overrides
-from .utils import log, _b2s, escape, unescape
from nonebot.adapters import Message as BaseMessage
from nonebot.adapters import MessageSegment as BaseMessageSegment
+from .utils import log, _b2s, escape, unescape
+
class MessageSegment(BaseMessageSegment["Message"]):
"""
@@ -27,23 +28,24 @@ class MessageSegment(BaseMessageSegment["Message"]):
# process special types
if type_ == "text":
- return escape(
- data.get("text", ""), # type: ignore
- escape_comma=False)
+ return escape(data.get("text", ""), escape_comma=False) # type: ignore
params = ",".join(
- [f"{k}={escape(str(v))}" for k, v in data.items() if v is not None])
+ [f"{k}={escape(str(v))}" for k, v in data.items() if v is not None]
+ )
return f"[CQ:{type_}{',' if params else ''}{params}]"
@overrides(BaseMessageSegment)
def __add__(self, other) -> "Message":
- return Message(self) + (MessageSegment.text(other) if isinstance(
- other, str) else other)
+ return Message(self) + (
+ MessageSegment.text(other) if isinstance(other, str) else other
+ )
@overrides(BaseMessageSegment)
def __radd__(self, other) -> "Message":
- return (MessageSegment.text(other)
- if isinstance(other, str) else Message(other)) + self
+ return (
+ MessageSegment.text(other) if isinstance(other, str) else Message(other)
+ ) + self
@overrides(BaseMessageSegment)
def is_text(self) -> bool:
@@ -83,11 +85,13 @@ class MessageSegment(BaseMessageSegment["Message"]):
return MessageSegment("forward", {"id": id_})
@staticmethod
- def image(file: Union[str, bytes, BytesIO, Path],
- type_: Optional[str] = None,
- cache: bool = True,
- proxy: bool = True,
- timeout: Optional[int] = None) -> "MessageSegment":
+ def image(
+ file: Union[str, bytes, BytesIO, Path],
+ type_: Optional[str] = None,
+ cache: bool = True,
+ proxy: bool = True,
+ timeout: Optional[int] = None,
+ ) -> "MessageSegment":
if isinstance(file, BytesIO):
file = file.getvalue()
if isinstance(file, bytes):
@@ -95,74 +99,85 @@ class MessageSegment(BaseMessageSegment["Message"]):
elif isinstance(file, Path):
file = f"file:///{file.resolve()}"
return MessageSegment(
- "image", {
+ "image",
+ {
"file": file,
"type": type_,
"cache": _b2s(cache),
"proxy": _b2s(proxy),
- "timeout": timeout
- })
+ "timeout": timeout,
+ },
+ )
@staticmethod
def json(data: str) -> "MessageSegment":
return MessageSegment("json", {"data": data})
@staticmethod
- def location(latitude: float,
- longitude: float,
- title: Optional[str] = None,
- content: Optional[str] = None) -> "MessageSegment":
+ def location(
+ latitude: float,
+ longitude: float,
+ title: Optional[str] = None,
+ content: Optional[str] = None,
+ ) -> "MessageSegment":
return MessageSegment(
- "location", {
+ "location",
+ {
"lat": str(latitude),
"lon": str(longitude),
"title": title,
- "content": content
- })
+ "content": content,
+ },
+ )
@staticmethod
def music(type_: str, id_: int) -> "MessageSegment":
return MessageSegment("music", {"type": type_, "id": id_})
@staticmethod
- def music_custom(url: str,
- audio: str,
- title: str,
- content: Optional[str] = None,
- img_url: Optional[str] = None) -> "MessageSegment":
+ def music_custom(
+ url: str,
+ audio: str,
+ title: str,
+ content: Optional[str] = None,
+ img_url: Optional[str] = None,
+ ) -> "MessageSegment":
return MessageSegment(
- "music", {
+ "music",
+ {
"type": "custom",
"url": url,
"audio": audio,
"title": title,
"content": content,
- "image": img_url
- })
+ "image": img_url,
+ },
+ )
@staticmethod
def node(id_: int) -> "MessageSegment":
return MessageSegment("node", {"id": str(id_)})
@staticmethod
- def node_custom(user_id: int, nickname: str,
- content: Union[str, "Message"]) -> "MessageSegment":
- return MessageSegment("node", {
- "user_id": str(user_id),
- "nickname": nickname,
- "content": content
- })
+ def node_custom(
+ user_id: int, nickname: str, content: Union[str, "Message"]
+ ) -> "MessageSegment":
+ return MessageSegment(
+ "node", {"user_id": str(user_id), "nickname": nickname, "content": content}
+ )
@staticmethod
def poke(type_: str, id_: str) -> "MessageSegment":
return MessageSegment("poke", {"type": type_, "id": id_})
@staticmethod
- def record(file: Union[str, bytes, BytesIO, Path],
- magic: Optional[bool] = None,
- cache: Optional[bool] = None,
- proxy: Optional[bool] = None,
- timeout: Optional[int] = None) -> "MessageSegment":
+ def record(
+ file: Union[str, bytes, BytesIO, Path],
+ magic: Optional[bool] = None,
+ cache: Optional[bool] = None,
+ proxy: Optional[bool] = None,
+ timeout: Optional[int] = None,
+ ) -> "MessageSegment":
if isinstance(file, BytesIO):
file = file.getvalue()
if isinstance(file, bytes):
@@ -170,13 +185,15 @@ class MessageSegment(BaseMessageSegment["Message"]):
elif isinstance(file, Path):
file = f"file:///{file.resolve()}"
return MessageSegment(
- "record", {
+ "record",
+ {
"file": file,
"magic": _b2s(magic),
"cache": _b2s(cache),
"proxy": _b2s(proxy),
- "timeout": timeout
- })
+ "timeout": timeout,
+ },
+ )
@staticmethod
def reply(id_: int) -> "MessageSegment":
@@ -191,26 +208,27 @@ class MessageSegment(BaseMessageSegment["Message"]):
return MessageSegment("shake", {})
@staticmethod
- def share(url: str = "",
- title: str = "",
- content: Optional[str] = None,
- image: Optional[str] = None) -> "MessageSegment":
- return MessageSegment("share", {
- "url": url,
- "title": title,
- "content": content,
- "image": image
- })
+ def share(
+ url: str = "",
+ title: str = "",
+ content: Optional[str] = None,
+ image: Optional[str] = None,
+ ) -> "MessageSegment":
+ return MessageSegment(
+ "share", {"url": url, "title": title, "content": content, "image": image}
+ )
@staticmethod
def text(text: str) -> "MessageSegment":
return MessageSegment("text", {"text": text})
@staticmethod
- def video(file: Union[str, bytes, BytesIO, Path],
- cache: Optional[bool] = None,
- proxy: Optional[bool] = None,
- timeout: Optional[int] = None) -> "MessageSegment":
+ def video(
+ file: Union[str, bytes, BytesIO, Path],
+ cache: Optional[bool] = None,
+ proxy: Optional[bool] = None,
+ timeout: Optional[int] = None,
+ ) -> "MessageSegment":
if isinstance(file, BytesIO):
file = file.getvalue()
if isinstance(file, bytes):
@@ -218,12 +236,14 @@ class MessageSegment(BaseMessageSegment["Message"]):
elif isinstance(file, Path):
file = f"file:///{file.resolve()}"
return MessageSegment(
- "video", {
+ "video",
+ {
"file": file,
"cache": _b2s(cache),
"proxy": _b2s(proxy),
- "timeout": timeout
- })
+ "timeout": timeout,
+ },
+ )
@staticmethod
def xml(data: str) -> "MessageSegment":
@@ -241,22 +261,22 @@ class Message(BaseMessage[MessageSegment]):
return MessageSegment
@overrides(BaseMessage)
- def __add__(self, other: Union[str, Mapping,
- Iterable[Mapping]]) -> "Message":
+ def __add__(self, other: Union[str, Mapping, Iterable[Mapping]]) -> "Message":
return super(Message, self).__add__(
- MessageSegment.text(other) if isinstance(other, str) else other)
+ MessageSegment.text(other) if isinstance(other, str) else other
+ )
@overrides(BaseMessage)
- def __radd__(self, other: Union[str, Mapping,
- Iterable[Mapping]]) -> "Message":
+ def __radd__(self, other: Union[str, Mapping, Iterable[Mapping]]) -> "Message":
return super(Message, self).__radd__(
- MessageSegment.text(other) if isinstance(other, str) else other)
+ MessageSegment.text(other) if isinstance(other, str) else other
+ )
@staticmethod
@overrides(BaseMessage)
def _construct(
- msg: Union[str, Mapping,
- Iterable[Mapping]]) -> Iterable[MessageSegment]:
+ msg: Union[str, Mapping, Iterable[Mapping]]
+ ) -> Iterable[MessageSegment]:
if isinstance(msg, Mapping):
msg = cast(Mapping[str, Any], msg)
yield MessageSegment(msg["type"], msg.get("data") or {})
@@ -270,14 +290,15 @@ class Message(BaseMessage[MessageSegment]):
def _iter_message(msg: str) -> Iterable[Tuple[str, str]]:
text_begin = 0
for cqcode in re.finditer(
- r"\[CQ:(?P[a-zA-Z0-9-_.]+)"
- r"(?P"
- r"(?:,[a-zA-Z0-9-_.]+=[^,\]]+)*"
- r"),?\]", msg):
- yield "text", msg[text_begin:cqcode.pos + cqcode.start()]
+ r"\[CQ:(?P[a-zA-Z0-9-_.]+)"
+ r"(?P"
+ r"(?:,[a-zA-Z0-9-_.]+=[^,\]]+)*"
+ r"),?\]",
+ msg,
+ ):
+ yield "text", msg[text_begin : cqcode.pos + cqcode.start()]
text_begin = cqcode.pos + cqcode.end()
- yield cqcode.group("type"), cqcode.group("params").lstrip(
- ",")
+ yield cqcode.group("type"), cqcode.group("params").lstrip(",")
yield "text", msg[text_begin:]
for type_, data in _iter_message(msg):
@@ -287,10 +308,11 @@ class Message(BaseMessage[MessageSegment]):
yield MessageSegment(type_, {"text": unescape(data)})
else:
data = {
- k: unescape(v) for k, v in map(
+ k: unescape(v)
+ for k, v in map(
lambda x: x.split("=", maxsplit=1),
- filter(lambda x: x, (
- x.lstrip() for x in data.split(","))))
+ filter(lambda x: x, (x.lstrip() for x in data.split(","))),
+ )
}
yield MessageSegment(type_, data)
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/permission.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/permission.py
index 09ea7b7a..2a85d6f1 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/permission.py
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/permission.py
@@ -1,5 +1,6 @@
from nonebot.adapters import Event
from nonebot.permission import Permission
+
from .event import GroupMessageEvent, PrivateMessageEvent
@@ -42,8 +43,7 @@ async def _group(event: Event) -> bool:
async def _group_member(event: Event) -> bool:
- return isinstance(event,
- GroupMessageEvent) and event.sender.role == "member"
+ return isinstance(event, GroupMessageEvent) and event.sender.role == "member"
async def _group_admin(event: Event) -> bool:
@@ -76,6 +76,12 @@ GROUP_OWNER = Permission(_group_owner)
"""
__all__ = [
- "PRIVATE", "PRIVATE_FRIEND", "PRIVATE_GROUP", "PRIVATE_OTHER", "GROUP",
- "GROUP_MEMBER", "GROUP_ADMIN", "GROUP_OWNER"
+ "PRIVATE",
+ "PRIVATE_FRIEND",
+ "PRIVATE_GROUP",
+ "PRIVATE_OTHER",
+ "GROUP",
+ "GROUP_MEMBER",
+ "GROUP_ADMIN",
+ "GROUP_OWNER",
]
diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/utils.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/utils.py
index 747b964f..a3d2d0e4 100644
--- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/utils.py
+++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/utils.py
@@ -16,9 +16,7 @@ def escape(s: str, *, escape_comma: bool = True) -> str:
* ``s: str``: 需要转义的字符串
* ``escape_comma: bool``: 是否转义逗号(``,``)。
"""
- s = s.replace("&", "&") \
- .replace("[", "[") \
- .replace("]", "]")
+ s = s.replace("&", "&").replace("[", "[").replace("]", "]")
if escape_comma:
s = s.replace(",", ",")
return s
@@ -34,10 +32,12 @@ def unescape(s: str) -> str:
* ``s: str``: 需要转义的字符串
"""
- return s.replace(",", ",") \
- .replace("[", "[") \
- .replace("]", "]") \
+ return (
+ s.replace(",", ",")
+ .replace("[", "[")
+ .replace("]", "]")
.replace("&", "&")
+ )
def _b2s(b: Optional[bool]) -> Optional[str]:
diff --git a/packages/nonebot-adapter-cqhttp/pyproject.toml b/packages/nonebot-adapter-cqhttp/pyproject.toml
index a500f04a..35386f9f 100644
--- a/packages/nonebot-adapter-cqhttp/pyproject.toml
+++ b/packages/nonebot-adapter-cqhttp/pyproject.toml
@@ -34,6 +34,21 @@ nonebot2 = { path = "../../", develop = true }
# url = "https://mirrors.aliyun.com/pypi/simple/"
# default = true
+[tool.black]
+line-length = 88
+target-version = ["py37", "py38", "py39"]
+include = '\.pyi?$'
+extend-exclude = '''
+'''
+
+[tool.isort]
+profile = "black"
+line_length = 80
+length_sort = true
+skip_gitignore = true
+force_sort_within_sections = true
+extra_standard_library = ["typing_extensions"]
+
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
diff --git a/packages/nonebot-adapter-ding/nonebot/adapters/ding/bot.py b/packages/nonebot-adapter-ding/nonebot/adapters/ding/bot.py
index dd8663f5..df5af674 100644
--- a/packages/nonebot-adapter-ding/nonebot/adapters/ding/bot.py
+++ b/packages/nonebot-adapter-ding/nonebot/adapters/ding/bot.py
@@ -16,10 +16,18 @@ from nonebot.drivers import Driver, HTTPRequest, HTTPResponse, HTTPConnection
from .config import Config as DingConfig
from .utils import log, calc_hmac_base64
from .message import Message, MessageSegment
-from .exception import (ActionFailed, NetworkError, SessionExpired,
- ApiNotAvailable)
-from .event import (MessageEvent, ConversationType, GroupMessageEvent,
- PrivateMessageEvent)
+from .exception import (
+ ActionFailed,
+ NetworkError,
+ SessionExpired,
+ ApiNotAvailable,
+)
+from .event import (
+ MessageEvent,
+ ConversationType,
+ GroupMessageEvent,
+ PrivateMessageEvent,
+)
if TYPE_CHECKING:
from nonebot.config import Config
@@ -31,6 +39,7 @@ class Bot(BaseBot):
"""
钉钉 协议 Bot 适配。继承属性参考 `BaseBot <./#class-basebot>`_ 。
"""
+
ding_config: DingConfig
@property
@@ -48,8 +57,8 @@ class Bot(BaseBot):
@classmethod
@overrides(BaseBot)
async def check_permission(
- cls, driver: Driver,
- request: HTTPConnection) -> Tuple[Optional[str], HTTPResponse]:
+ cls, driver: Driver, request: HTTPConnection
+ ) -> Tuple[Optional[str], HTTPResponse]:
"""
:说明:
@@ -61,7 +70,8 @@ class Bot(BaseBot):
# 检查连接方式
if not isinstance(request, HTTPRequest):
return None, HTTPResponse(
- 405, b"Unsupported connection type, available type: `http`")
+ 405, b"Unsupported connection type, available type: `http`"
+ )
# 检查 timestamp
if not timestamp:
@@ -74,13 +84,15 @@ class Bot(BaseBot):
log("WARNING", "Missing Signature Header")
return None, HTTPResponse(400, b"Missing `sign` Header")
sign_base64 = calc_hmac_base64(str(timestamp), secret)
- if sign != sign_base64.decode('utf-8'):
+ if sign != sign_base64.decode("utf-8"):
log("WARNING", "Signature Header is invalid")
return None, HTTPResponse(403, b"Signature is invalid")
else:
log("WARNING", "Ding signature check ignored!")
- return (json.loads(request.body.decode())["chatbotUserId"],
- HTTPResponse(204, b''))
+ return (
+ json.loads(request.body.decode())["chatbotUserId"],
+ HTTPResponse(204, b""),
+ )
@overrides(BaseBot)
async def handle_message(self, message: bytes):
@@ -111,10 +123,9 @@ class Bot(BaseBot):
return
@overrides(BaseBot)
- async def _call_api(self,
- api: str,
- event: Optional[MessageEvent] = None,
- **data) -> Any:
+ async def _call_api(
+ self, api: str, event: Optional[MessageEvent] = None, **data
+ ) -> Any:
if not isinstance(self.request, HTTPRequest):
log("ERROR", "Only support http connection.")
return
@@ -138,7 +149,8 @@ class Bot(BaseBot):
if event:
# 确保 sessionWebhook 没有过期
if int(datetime.now().timestamp()) > int(
- event.sessionWebhookExpiredTime / 1000):
+ event.sessionWebhookExpiredTime / 1000
+ ):
raise SessionExpired
webhook = event.sessionWebhook
@@ -150,32 +162,37 @@ class Bot(BaseBot):
if not message:
raise ValueError("Message not found")
try:
- async with httpx.AsyncClient(headers=headers,
- follow_redirects=True) as client:
- response = await client.post(webhook,
- params=params,
- json=message._produce(),
- timeout=self.config.api_timeout)
+ async with httpx.AsyncClient(
+ headers=headers, follow_redirects=True
+ ) as client:
+ response = await client.post(
+ webhook,
+ params=params,
+ json=message._produce(),
+ timeout=self.config.api_timeout,
+ )
if 200 <= response.status_code < 300:
result = response.json()
if isinstance(result, dict):
if result.get("errcode") != 0:
- raise ActionFailed(errcode=result.get("errcode"),
- errmsg=result.get("errmsg"))
+ raise ActionFailed(
+ errcode=result.get("errcode"), errmsg=result.get("errmsg")
+ )
return result
- raise NetworkError(f"HTTP request received unexpected "
- f"status code: {response.status_code}")
+ raise NetworkError(
+ f"HTTP request received unexpected "
+ f"status code: {response.status_code}"
+ )
except httpx.InvalidURL:
raise NetworkError("API root url invalid")
except httpx.HTTPError:
raise NetworkError("HTTP request failed")
@overrides(BaseBot)
- async def call_api(self,
- api: str,
- event: Optional[MessageEvent] = None,
- **data) -> Any:
+ async def call_api(
+ self, api: str, event: Optional[MessageEvent] = None, **data
+ ) -> Any:
"""
:说明:
@@ -199,13 +216,15 @@ class Bot(BaseBot):
return await super().call_api(api, event=event, **data)
@overrides(BaseBot)
- async def send(self,
- event: MessageEvent,
- message: Union[str, "Message", "MessageSegment"],
- at_sender: bool = False,
- webhook: Optional[str] = None,
- secret: Optional[str] = None,
- **kwargs) -> Any:
+ async def send(
+ self,
+ event: MessageEvent,
+ message: Union[str, "Message", "MessageSegment"],
+ at_sender: bool = False,
+ webhook: Optional[str] = None,
+ secret: Optional[str] = None,
+ **kwargs,
+ ) -> Any:
"""
:说明:
@@ -241,9 +260,11 @@ class Bot(BaseBot):
params.update(kwargs)
if at_sender and event.conversationType != ConversationType.private:
- params[
- "message"] = f"@{event.senderId} " + msg + MessageSegment.atDingtalkIds(
- event.senderId)
+ params["message"] = (
+ f"@{event.senderId} "
+ + msg
+ + MessageSegment.atDingtalkIds(event.senderId)
+ )
else:
params["message"] = msg
diff --git a/packages/nonebot-adapter-ding/nonebot/adapters/ding/config.py b/packages/nonebot-adapter-ding/nonebot/adapters/ding/config.py
index 405fb2c5..9c88b1b7 100644
--- a/packages/nonebot-adapter-ding/nonebot/adapters/ding/config.py
+++ b/packages/nonebot-adapter-ding/nonebot/adapters/ding/config.py
@@ -12,6 +12,7 @@ class Config(BaseModel):
- ``access_token`` / ``ding_access_token``: 钉钉令牌
- ``secret`` / ``ding_secret``: 钉钉 HTTP 上报数据签名口令
"""
+
secret: Optional[str] = Field(default=None, alias="ding_secret")
access_token: Optional[str] = Field(default=None, alias="ding_access_token")
diff --git a/packages/nonebot-adapter-ding/nonebot/adapters/ding/event.py b/packages/nonebot-adapter-ding/nonebot/adapters/ding/event.py
index e01588a6..ad9eb230 100644
--- a/packages/nonebot-adapter-ding/nonebot/adapters/ding/event.py
+++ b/packages/nonebot-adapter-ding/nonebot/adapters/ding/event.py
@@ -69,6 +69,7 @@ class ConversationType(str, Enum):
class MessageEvent(Event):
"""消息事件"""
+
msgtype: str
text: TextMessage
msgId: str
@@ -88,11 +89,10 @@ class MessageEvent(Event):
def gen_message(cls, values: dict):
assert "msgtype" in values, "msgtype must be specified"
# 其实目前钉钉机器人只能接收到 text 类型的消息
- assert values[
- "msgtype"] in values, f"{values['msgtype']} must be specified"
- content = values[values['msgtype']]['content']
+ assert values["msgtype"] in values, f"{values['msgtype']} must be specified"
+ content = values[values["msgtype"]]["content"]
# 如果是被 @,第一个字符将会为空格,移除特殊情况
- if content[0] == ' ':
+ if content[0] == " ":
content = content[1:]
values["message"] = content
return values
@@ -128,6 +128,7 @@ class MessageEvent(Event):
class PrivateMessageEvent(MessageEvent):
"""私聊消息事件"""
+
chatbotCorpId: str
senderStaffId: Optional[str]
conversationType: ConversationType = ConversationType.private
@@ -135,6 +136,7 @@ class PrivateMessageEvent(MessageEvent):
class GroupMessageEvent(MessageEvent):
"""群消息事件"""
+
atUsers: List[AtUsersItem]
conversationType: ConversationType = ConversationType.group
conversationTitle: str
diff --git a/packages/nonebot-adapter-ding/nonebot/adapters/ding/exception.py b/packages/nonebot-adapter-ding/nonebot/adapters/ding/exception.py
index df416932..73b08b43 100644
--- a/packages/nonebot-adapter-ding/nonebot/adapters/ding/exception.py
+++ b/packages/nonebot-adapter-ding/nonebot/adapters/ding/exception.py
@@ -1,9 +1,9 @@
from typing import Optional
-from nonebot.exception import (AdapterException, ActionFailed as
- BaseActionFailed, ApiNotAvailable as
- BaseApiNotAvailable, NetworkError as
- BaseNetworkError)
+from nonebot.exception import AdapterException
+from nonebot.exception import ActionFailed as BaseActionFailed
+from nonebot.exception import NetworkError as BaseNetworkError
+from nonebot.exception import ApiNotAvailable as BaseApiNotAvailable
class DingAdapterException(AdapterException):
@@ -29,15 +29,13 @@ class ActionFailed(BaseActionFailed, DingAdapterException):
* ``errmsg: Optional[str]``: 错误信息
"""
- def __init__(self,
- errcode: Optional[int] = None,
- errmsg: Optional[str] = None):
+ def __init__(self, errcode: Optional[int] = None, errmsg: Optional[str] = None):
super().__init__()
self.errcode = errcode
self.errmsg = errmsg
def __repr__(self):
- return f""
+ return f''
def __str__(self):
return self.__repr__()
diff --git a/packages/nonebot-adapter-ding/nonebot/adapters/ding/message.py b/packages/nonebot-adapter-ding/nonebot/adapters/ding/message.py
index 98d13f7d..ef092739 100644
--- a/packages/nonebot-adapter-ding/nonebot/adapters/ding/message.py
+++ b/packages/nonebot-adapter-ding/nonebot/adapters/ding/message.py
@@ -77,10 +77,9 @@ class MessageSegment(BaseMessageSegment["Message"]):
def code(code_language: str, code: str) -> "Message":
"""发送 code 消息段"""
message = MessageSegment.text(code)
- message += MessageSegment.extension({
- "text_type": "code_snippet",
- "code_language": code_language
- })
+ message += MessageSegment.extension(
+ {"text_type": "code_snippet", "code_language": code_language}
+ )
return message
@staticmethod
@@ -95,16 +94,19 @@ class MessageSegment(BaseMessageSegment["Message"]):
)
@staticmethod
- def actionCardSingleBtn(title: str, text: str, singleTitle: str,
- singleURL) -> "MessageSegment":
+ def actionCardSingleBtn(
+ title: str, text: str, singleTitle: str, singleURL
+ ) -> "MessageSegment":
"""发送 ``actionCardSingleBtn`` 类型消息"""
return MessageSegment(
- "actionCard", {
+ "actionCard",
+ {
"title": title,
"text": text,
"singleTitle": singleTitle,
- "singleURL": singleURL
- })
+ "singleURL": singleURL,
+ },
+ )
@staticmethod
def actionCardMultiBtns(
@@ -112,7 +114,7 @@ class MessageSegment(BaseMessageSegment["Message"]):
text: str,
btns: list,
hideAvatar: bool = False,
- btnOrientation: str = '1',
+ btnOrientation: str = "1",
) -> "MessageSegment":
"""
发送 ``actionCardMultiBtn`` 类型消息
@@ -123,13 +125,15 @@ class MessageSegment(BaseMessageSegment["Message"]):
* ``btns``: ``[{ "title": title, "actionURL": actionURL }, ...]``
"""
return MessageSegment(
- "actionCard", {
+ "actionCard",
+ {
"title": title,
"text": text,
"hideAvatar": "1" if hideAvatar else "0",
"btnOrientation": btnOrientation,
- "btns": btns
- })
+ "btns": btns,
+ },
+ )
@staticmethod
def feedCard(links: list) -> "MessageSegment":
@@ -144,7 +148,7 @@ class MessageSegment(BaseMessageSegment["Message"]):
@staticmethod
def raw(data) -> "MessageSegment":
- return MessageSegment('raw', data)
+ return MessageSegment("raw", data)
def to_dict(self) -> Dict[str, Any]:
# 让用户可以直接发送原始的消息格式
@@ -171,8 +175,8 @@ class Message(BaseMessage[MessageSegment]):
@staticmethod
@overrides(BaseMessage)
def _construct(
- msg: Union[str, Mapping,
- Iterable[Mapping]]) -> Iterable[MessageSegment]:
+ msg: Union[str, Mapping, Iterable[Mapping]]
+ ) -> Iterable[MessageSegment]:
if isinstance(msg, Mapping):
msg = cast(Mapping[str, Any], msg)
yield MessageSegment(msg["type"], msg.get("data") or {})
@@ -187,10 +191,11 @@ class Message(BaseMessage[MessageSegment]):
segment: MessageSegment
for segment in self:
# text 可以和 text 合并
- if segment.type == "text" and data.get("msgtype") == 'text':
+ if segment.type == "text" and data.get("msgtype") == "text":
data.setdefault("text", {})
- data["text"]["content"] = data["text"].setdefault(
- "content", "") + segment.data["content"]
+ data["text"]["content"] = (
+ data["text"].setdefault("content", "") + segment.data["content"]
+ )
else:
data.update(segment.to_dict())
return data
diff --git a/packages/nonebot-adapter-ding/nonebot/adapters/ding/utils.py b/packages/nonebot-adapter-ding/nonebot/adapters/ding/utils.py
index 5529d42b..cf77a552 100644
--- a/packages/nonebot-adapter-ding/nonebot/adapters/ding/utils.py
+++ b/packages/nonebot-adapter-ding/nonebot/adapters/ding/utils.py
@@ -8,10 +8,10 @@ log = logger_wrapper("DING")
def calc_hmac_base64(timestamp: str, secret: str):
- secret_enc = secret.encode('utf-8')
- string_to_sign = '{}\n{}'.format(timestamp, secret)
- string_to_sign_enc = string_to_sign.encode('utf-8')
- hmac_code = hmac.new(secret_enc,
- string_to_sign_enc,
- digestmod=hashlib.sha256).digest()
+ secret_enc = secret.encode("utf-8")
+ string_to_sign = "{}\n{}".format(timestamp, secret)
+ string_to_sign_enc = string_to_sign.encode("utf-8")
+ hmac_code = hmac.new(
+ secret_enc, string_to_sign_enc, digestmod=hashlib.sha256
+ ).digest()
return base64.b64encode(hmac_code)
diff --git a/packages/nonebot-adapter-ding/pyproject.toml b/packages/nonebot-adapter-ding/pyproject.toml
index 755499ec..2ee57d3d 100644
--- a/packages/nonebot-adapter-ding/pyproject.toml
+++ b/packages/nonebot-adapter-ding/pyproject.toml
@@ -34,6 +34,21 @@ nonebot2 = { path = "../../", develop = true }
# url = "https://mirrors.aliyun.com/pypi/simple/"
# default = true
+[tool.black]
+line-length = 88
+target-version = ["py37", "py38", "py39"]
+include = '\.pyi?$'
+extend-exclude = '''
+'''
+
+[tool.isort]
+profile = "black"
+line_length = 80
+length_sort = true
+skip_gitignore = true
+force_sort_within_sections = true
+extra_standard_library = ["typing_extensions"]
+
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
diff --git a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/__init__.py b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/__init__.py
index 49f6e956..d9e2cdfb 100644
--- a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/__init__.py
+++ b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/__init__.py
@@ -7,7 +7,7 @@ aiocache_logger.setLevel(logging.DEBUG)
aiocache_logger.handlers.clear()
aiocache_logger.addHandler(LoguruHandler())
-from .bot import Bot as Bot
from .event import *
+from .bot import Bot as Bot
from .message import Message as Message
from .message import MessageSegment as MessageSegment
diff --git a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/bot.py b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/bot.py
index c3ab6cc8..6fa3756c 100644
--- a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/bot.py
+++ b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/bot.py
@@ -1,24 +1,39 @@
import re
import json
-from typing import (TYPE_CHECKING, Any, Dict, Tuple, Union, Iterable, Optional,
- AsyncIterable, cast)
+from typing import (
+ TYPE_CHECKING,
+ Any,
+ Dict,
+ Tuple,
+ Union,
+ Iterable,
+ Optional,
+ AsyncIterable,
+ cast,
+)
import httpx
from aiocache import Cache, cached
from aiocache.serializers import PickleSerializer
from nonebot.log import logger
-from .utils import AESCipher, log
from nonebot.typing import overrides
from nonebot.utils import escape_tag
from nonebot.message import handle_event
-from .config import Config as FeishuConfig
from nonebot.adapters import Bot as BaseBot
from nonebot.drivers import Driver, HTTPRequest, HTTPResponse
+
+from .utils import AESCipher, log
+from .config import Config as FeishuConfig
from .message import Message, MessageSegment, MessageSerializer
from .exception import ActionFailed, NetworkError, ApiNotAvailable
-from .event import (Event, MessageEvent, GroupMessageEvent, PrivateMessageEvent,
- get_event_model)
+from .event import (
+ Event,
+ MessageEvent,
+ GroupMessageEvent,
+ PrivateMessageEvent,
+ get_event_model,
+)
if TYPE_CHECKING:
from nonebot.config import Config
@@ -47,8 +62,10 @@ def _check_at_me(bot: "Bot", event: "Event"):
event.to_me = True
for index, segment in enumerate(message):
- if segment.type == "at" and segment.data.get(
- "user_name") in bot.config.nickname:
+ if (
+ segment.type == "at"
+ and segment.data.get("user_name") in bot.config.nickname
+ ):
event.to_me = True
del event.event.message.content[index]
return
@@ -57,7 +74,8 @@ def _check_at_me(bot: "Bot", event: "Event"):
if mention["name"] in bot.config.nickname:
event.to_me = True
segment.data["text"] = segment.data["text"].replace(
- f"@{mention['name']}", "")
+ f"@{mention['name']}", ""
+ )
segment.data["text"] = segment.data["text"].lstrip()
break
else:
@@ -92,18 +110,18 @@ def _check_nickname(bot: "Bot", event: "Event"):
if nicknames:
# check if the user is calling me with my nickname
nickname_regex = "|".join(nicknames)
- m = re.search(rf"^({nickname_regex})([\s,,]*|$)", first_text,
- re.IGNORECASE)
+ m = re.search(rf"^({nickname_regex})([\s,,]*|$)", first_text, re.IGNORECASE)
if m:
nickname = m.group(1)
log("DEBUG", f"User is calling me {nickname}")
event.to_me = True
- first_msg_seg.data["text"] = first_text[m.end():]
+ first_msg_seg.data["text"] = first_text[m.end() :]
def _handle_api_result(
- result: Union[Optional[Dict[str, Any]], str, bytes, Iterable[bytes],
- AsyncIterable[bytes]]
+ result: Union[
+ Optional[Dict[str, Any]], str, bytes, Iterable[bytes], AsyncIterable[bytes]
+ ]
) -> Any:
"""
:说明:
@@ -155,13 +173,13 @@ class Bot(BaseBot):
@classmethod
@overrides(BaseBot)
async def check_permission(
- cls, driver: Driver, request: HTTPRequest
+ cls, driver: Driver, request: HTTPRequest
) -> Tuple[Optional[str], Optional[HTTPResponse]]:
if not isinstance(request, HTTPRequest):
- log("WARNING",
- "Unsupported connection type, available type: `http`")
+ log("WARNING", "Unsupported connection type, available type: `http`")
return None, HTTPResponse(
- 405, b"Unsupported connection type, available type: `http`")
+ 405, b"Unsupported connection type, available type: `http`"
+ )
encrypt_key = cls.feishu_config.encrypt_key
if encrypt_key:
@@ -174,16 +192,13 @@ class Bot(BaseBot):
challenge = data.get("challenge")
if challenge:
return data.get("token"), HTTPResponse(
- 200,
- json.dumps({
- "challenge": challenge
- }).encode())
+ 200, json.dumps({"challenge": challenge}).encode()
+ )
schema = data.get("schema")
if not schema:
return None, HTTPResponse(
- 400,
- b"Missing `schema` in POST body, only accept event of version 2.0"
+ 400, b"Missing `schema` in POST body, only accept event of version 2.0"
)
headers = data.get("header")
@@ -196,15 +211,13 @@ class Bot(BaseBot):
if not token:
log("WARNING", "Missing `verification token` in POST body")
- return None, HTTPResponse(
- 400, b"Missing `verification token` in POST body")
+ return None, HTTPResponse(400, b"Missing `verification token` in POST body")
else:
if token != cls.feishu_config.verification_token:
log("WARNING", "Verification token check failed")
- return None, HTTPResponse(403,
- b"Verification token check failed")
+ return None, HTTPResponse(403, b"Verification token check failed")
- return app_id, HTTPResponse(200, b'')
+ return app_id, HTTPResponse(200, b"")
async def handle_message(self, message: bytes):
"""
@@ -245,28 +258,32 @@ class Bot(BaseBot):
def _construct_url(self, path: str) -> str:
return self.api_root + path
- @cached(ttl=60 * 60,
- cache=Cache.MEMORY,
- key="_feishu_tenant_access_token",
- serializer=PickleSerializer())
+ @cached(
+ ttl=60 * 60,
+ cache=Cache.MEMORY,
+ key="_feishu_tenant_access_token",
+ serializer=PickleSerializer(),
+ )
async def _fetch_tenant_access_token(self) -> str:
try:
async with httpx.AsyncClient(follow_redirects=True) as client:
response = await client.post(
- self._construct_url(
- "auth/v3/tenant_access_token/internal/"),
+ self._construct_url("auth/v3/tenant_access_token/internal/"),
json={
"app_id": self.feishu_config.app_id,
- "app_secret": self.feishu_config.app_secret
+ "app_secret": self.feishu_config.app_secret,
},
- timeout=self.config.api_timeout)
+ timeout=self.config.api_timeout,
+ )
if 200 <= response.status_code < 300:
result = response.json()
return result["tenant_access_token"]
else:
- raise NetworkError(f"HTTP request received unexpected "
- f"status code: {response.status_code}")
+ raise NetworkError(
+ f"HTTP request received unexpected "
+ f"status code: {response.status_code}"
+ )
except httpx.InvalidURL:
raise NetworkError("API root url invalid")
except httpx.HTTPError:
@@ -280,30 +297,37 @@ class Bot(BaseBot):
raise ApiNotAvailable
headers = {}
- self.feishu_config.tenant_access_token = await self._fetch_tenant_access_token(
+ self.feishu_config.tenant_access_token = (
+ await self._fetch_tenant_access_token()
+ )
+ headers["Authorization"] = (
+ "Bearer " + self.feishu_config.tenant_access_token
)
- headers[
- "Authorization"] = "Bearer " + self.feishu_config.tenant_access_token
try:
- async with httpx.AsyncClient(timeout=self.config.api_timeout,
- follow_redirects=True) as client:
+ async with httpx.AsyncClient(
+ timeout=self.config.api_timeout, follow_redirects=True
+ ) as client:
response = await client.send(
- httpx.Request(data["method"],
- self.api_root + api,
- json=data.get("body", {}),
- params=data.get("query", {}),
- headers=headers))
+ httpx.Request(
+ data["method"],
+ self.api_root + api,
+ json=data.get("body", {}),
+ params=data.get("query", {}),
+ headers=headers,
+ )
+ )
if 200 <= response.status_code < 300:
- if response.headers["content-type"].startswith(
- "application/json"):
+ if response.headers["content-type"].startswith("application/json"):
result = response.json()
else:
result = response.content
return _handle_api_result(result)
- raise NetworkError(f"HTTP request received unexpected "
- f"status code: {response.status_code} "
- f"response body: {response.text}")
+ raise NetworkError(
+ f"HTTP request received unexpected "
+ f"status code: {response.status_code} "
+ f"response body: {response.text}"
+ )
except httpx.InvalidURL:
raise NetworkError("API root url invalid")
except httpx.HTTPError:
@@ -333,11 +357,13 @@ class Bot(BaseBot):
return await super().call_api(api, **data)
@overrides(BaseBot)
- async def send(self,
- event: Event,
- message: Union[str, Message, MessageSegment],
- at_sender: bool = False,
- **kwargs) -> Any:
+ async def send(
+ self,
+ event: Event,
+ message: Union[str, Message, MessageSegment],
+ at_sender: bool = False,
+ **kwargs,
+ ) -> Any:
msg = message if isinstance(message, Message) else Message(message)
if isinstance(event, GroupMessageEvent):
@@ -346,7 +372,8 @@ class Bot(BaseBot):
receive_id, receive_id_type = event.get_user_id(), "open_id"
else:
raise ValueError(
- "Cannot guess `receive_id` and `receive_id_type` to reply!")
+ "Cannot guess `receive_id` and `receive_id_type` to reply!"
+ )
at_sender = at_sender and bool(event.get_user_id())
@@ -357,14 +384,12 @@ class Bot(BaseBot):
params = {
"method": "POST",
- "query": {
- "receive_id_type": receive_id_type
- },
+ "query": {"receive_id_type": receive_id_type},
"body": {
"receive_id": receive_id,
"content": content,
- "msg_type": msg_type
- }
+ "msg_type": msg_type,
+ },
}
return await self.call_api(f"im/v1/messages", **params)
diff --git a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/config.py b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/config.py
index 4d74a1de..4bc70c12 100644
--- a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/config.py
+++ b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/config.py
@@ -17,13 +17,16 @@ class Config(BaseModel):
- ``is_lark`` / ``feishu_is_lark``: 是否使用Lark(飞书海外版),默认为 false
"""
+
app_id: Optional[str] = Field(default=None, alias="feishu_app_id")
app_secret: Optional[str] = Field(default=None, alias="feishu_app_secret")
encrypt_key: Optional[str] = Field(default=None, alias="feishu_encrypt_key")
- verification_token: Optional[str] = Field(default=None,
- alias="feishu_verification_token")
+ verification_token: Optional[str] = Field(
+ default=None, alias="feishu_verification_token"
+ )
tenant_access_token: Optional[str] = Field(
- default=None, alias="feishu_tenant_access_token")
+ default=None, alias="feishu_tenant_access_token"
+ )
is_lark: Optional[str] = Field(default=False, alias="feishu_is_lark")
class Config:
diff --git a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/event.py b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/event.py
index 9c35ea9e..620bbe36 100644
--- a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/event.py
+++ b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/event.py
@@ -1,12 +1,12 @@
-import inspect
import json
-from typing import Any, Dict, List, Literal, Optional, Type
+import inspect
+from typing import Any, Dict, List, Type, Literal, Optional
-from pydantic import BaseModel, Field, root_validator
from pygtrie import StringTrie
+from pydantic import Field, BaseModel, root_validator
-from nonebot.adapters import Event as BaseEvent
from nonebot.typing import overrides
+from nonebot.adapters import Event as BaseEvent
from .message import Message, MessageDeserializer
diff --git a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/exception.py b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/exception.py
index 38336e53..99fb562c 100644
--- a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/exception.py
+++ b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/exception.py
@@ -1,13 +1,12 @@
from typing import Optional
-from nonebot.exception import ActionFailed as BaseActionFailed
from nonebot.exception import AdapterException
-from nonebot.exception import ApiNotAvailable as BaseApiNotAvailable
+from nonebot.exception import ActionFailed as BaseActionFailed
from nonebot.exception import NetworkError as BaseNetworkError
+from nonebot.exception import ApiNotAvailable as BaseApiNotAvailable
class FeishuAdapterException(AdapterException):
-
def __init__(self):
super().__init__("feishu")
@@ -28,8 +27,11 @@ class ActionFailed(BaseActionFailed, FeishuAdapterException):
self.info = kwargs
def __repr__(self):
- return f""
+ return (
+ f""
+ )
def __str__(self):
return self.__repr__()
diff --git a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/message.py b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/message.py
index d9a7e2a1..7e7eabd9 100644
--- a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/message.py
+++ b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/message.py
@@ -1,8 +1,18 @@
import json
import itertools
from dataclasses import dataclass
-from typing import (Any, Dict, List, Type, Tuple, Union, Mapping, Iterable,
- Optional, cast)
+from typing import (
+ Any,
+ Dict,
+ List,
+ Type,
+ Tuple,
+ Union,
+ Mapping,
+ Iterable,
+ Optional,
+ cast,
+)
from nonebot.typing import overrides
from nonebot.adapters import Message as BaseMessage
@@ -34,7 +44,7 @@ class MessageSegment(BaseMessageSegment["Message"]):
"share_user": "[个人名片]",
"system": "[系统消息]",
"location": "[位置]",
- "video_chat": "[视频通话]"
+ "video_chat": "[视频通话]",
}
def __str__(self) -> str:
@@ -47,24 +57,26 @@ class MessageSegment(BaseMessageSegment["Message"]):
@overrides(BaseMessageSegment)
def __add__(self, other) -> "Message":
- return Message(self) + (MessageSegment.text(other) if isinstance(
- other, str) else other)
+ return Message(self) + (
+ MessageSegment.text(other) if isinstance(other, str) else other
+ )
@overrides(BaseMessageSegment)
def __radd__(self, other) -> "Message":
- return (MessageSegment.text(other)
- if isinstance(other, str) else Message(other)) + self
+ return (
+ MessageSegment.text(other) if isinstance(other, str) else Message(other)
+ ) + self
@overrides(BaseMessageSegment)
def is_text(self) -> bool:
return self.type == "text"
- #接收消息
+ # 接收消息
@staticmethod
def at(user_id: str) -> "MessageSegment":
return MessageSegment("at", {"user_id": user_id})
- #发送消息
+ # 发送消息
@staticmethod
def text(text: str) -> "MessageSegment":
return MessageSegment("text", {"text": text})
@@ -79,10 +91,7 @@ class MessageSegment(BaseMessageSegment["Message"]):
@staticmethod
def interactive(title: str, elements: list) -> "MessageSegment":
- return MessageSegment("interactive", {
- "title": title,
- "elements": elements
- })
+ return MessageSegment("interactive", {"title": title, "elements": elements})
@staticmethod
def share_chat(chat_id: str) -> "MessageSegment":
@@ -94,28 +103,25 @@ class MessageSegment(BaseMessageSegment["Message"]):
@staticmethod
def audio(file_key: str, duration: int) -> "MessageSegment":
- return MessageSegment("audio", {
- "file_key": file_key,
- "duration": duration
- })
+ return MessageSegment("audio", {"file_key": file_key, "duration": duration})
@staticmethod
- def media(file_key: str, image_key: str, file_name: str,
- duration: int) -> "MessageSegment":
+ def media(
+ file_key: str, image_key: str, file_name: str, duration: int
+ ) -> "MessageSegment":
return MessageSegment(
- "media", {
+ "media",
+ {
"file_key": file_key,
"image_key": image_key,
"file_name": file_name,
- "duration": duration
- })
+ "duration": duration,
+ },
+ )
@staticmethod
def file(file_key: str, file_name: str) -> "MessageSegment":
- return MessageSegment("file", {
- "file_key": file_key,
- "file_name": file_name
- })
+ return MessageSegment("file", {"file_key": file_key, "file_name": file_name})
@staticmethod
def sticker(file_key) -> "MessageSegment":
@@ -133,22 +139,22 @@ class Message(BaseMessage[MessageSegment]):
return MessageSegment
@overrides(BaseMessage)
- def __add__(self, other: Union[str, Mapping,
- Iterable[Mapping]]) -> "Message":
+ def __add__(self, other: Union[str, Mapping, Iterable[Mapping]]) -> "Message":
return super(Message, self).__add__(
- MessageSegment.text(other) if isinstance(other, str) else other)
+ MessageSegment.text(other) if isinstance(other, str) else other
+ )
@overrides(BaseMessage)
- def __radd__(self, other: Union[str, Mapping,
- Iterable[Mapping]]) -> "Message":
+ def __radd__(self, other: Union[str, Mapping, Iterable[Mapping]]) -> "Message":
return super(Message, self).__radd__(
- MessageSegment.text(other) if isinstance(other, str) else other)
+ MessageSegment.text(other) if isinstance(other, str) else other
+ )
@staticmethod
@overrides(BaseMessage)
def _construct(
- msg: Union[str, Mapping,
- Iterable[Mapping]]) -> Iterable[MessageSegment]:
+ msg: Union[str, Mapping, Iterable[Mapping]]
+ ) -> Iterable[MessageSegment]:
if isinstance(msg, Mapping):
msg = cast(Mapping[str, Any], msg)
yield MessageSegment(msg["type"], msg.get("data") or {})
@@ -169,7 +175,8 @@ class Message(BaseMessage[MessageSegment]):
for i, seg in enumerate(self):
if seg.type == "text" and i != 0 and msg[-1].type == "text":
msg[-1] = MessageSegment(
- "text", {"text": msg[-1].data["text"] + seg.data["text"]})
+ "text", {"text": msg[-1].data["text"] + seg.data["text"]}
+ )
else:
msg.append(seg)
return Message(msg)
@@ -184,6 +191,7 @@ class MessageSerializer:
"""
飞书 协议 Message 序列化器。
"""
+
message: Message
def serialize(self) -> Tuple[str, str]:
@@ -198,10 +206,12 @@ class MessageSerializer:
else:
if last_segment_type == "image":
msg["content"].append([])
- msg["content"][-1].append({
- "tag": segment.type if segment.type != "image" else "img",
- **segment.data
- })
+ msg["content"][-1].append(
+ {
+ "tag": segment.type if segment.type != "image" else "img",
+ **segment.data,
+ }
+ )
last_segment_type = segment.type
return "post", json.dumps({"zh_cn": {**msg}})
@@ -214,6 +224,7 @@ class MessageDeserializer:
"""
飞书 协议 Message 反序列化器。
"""
+
type: str
data: Dict[str, Any]
mentions: Optional[List[dict]]
@@ -227,14 +238,13 @@ class MessageDeserializer:
if self.type == "post":
msg = Message()
if self.data["title"] != "":
- msg += MessageSegment("text", {'text': self.data["title"]})
+ msg += MessageSegment("text", {"text": self.data["title"]})
for seg in itertools.chain(*self.data["content"]):
tag = seg.pop("tag")
if tag == "at":
seg["user_name"] = dict_mention[seg["user_id"]]["name"]
- seg["user_id"] = dict_mention[
- seg["user_id"]]["id"]["open_id"]
+ seg["user_id"] = dict_mention[seg["user_id"]]["id"]["open_id"]
msg += MessageSegment(tag if tag != "img" else "image", seg)
@@ -242,7 +252,8 @@ class MessageDeserializer:
elif self.type == "text":
for key, mention in dict_mention.items():
self.data["text"] = self.data["text"].replace(
- key, f"@{mention['name']}")
+ key, f"@{mention['name']}"
+ )
self.data["mentions"] = dict_mention
return Message(MessageSegment(self.type, self.data))
diff --git a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/utils.py b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/utils.py
index ba418356..8848e563 100644
--- a/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/utils.py
+++ b/packages/nonebot-adapter-feishu/nonebot/adapters/feishu/utils.py
@@ -9,27 +9,26 @@ log = logger_wrapper("FEISHU")
class AESCipher(object):
-
def __init__(self, key):
self.block_size = AES.block_size
self.key = hashlib.sha256(AESCipher.str_to_bytes(key)).digest()
@staticmethod
def str_to_bytes(data):
- u_type = type(b"".decode('utf8'))
+ u_type = type(b"".decode("utf8"))
if isinstance(data, u_type):
- return data.encode('utf8')
+ return data.encode("utf8")
return data
@staticmethod
def _unpad(s):
- return s[:-ord(s[len(s) - 1:])]
+ return s[: -ord(s[len(s) - 1 :])]
def decrypt(self, enc):
- iv = enc[:AES.block_size]
+ iv = enc[: AES.block_size]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
- return self._unpad(cipher.decrypt(enc[AES.block_size:]))
+ return self._unpad(cipher.decrypt(enc[AES.block_size :]))
def decrypt_string(self, enc):
enc = base64.b64decode(enc)
- return self.decrypt(enc).decode('utf8')
+ return self.decrypt(enc).decode("utf8")
diff --git a/packages/nonebot-adapter-feishu/pyproject.toml b/packages/nonebot-adapter-feishu/pyproject.toml
index 030852e9..c3dfd427 100644
--- a/packages/nonebot-adapter-feishu/pyproject.toml
+++ b/packages/nonebot-adapter-feishu/pyproject.toml
@@ -36,6 +36,21 @@ nonebot2 = { path = "../../", develop = true }
# url = "https://mirrors.aliyun.com/pypi/simple/"
# default = true
+[tool.black]
+line-length = 88
+target-version = ["py37", "py38", "py39"]
+include = '\.pyi?$'
+extend-exclude = '''
+'''
+
+[tool.isort]
+profile = "black"
+line_length = 80
+length_sort = true
+skip_gitignore = true
+force_sort_within_sections = true
+extra_standard_library = ["typing_extensions"]
+
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/bot.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/bot.py
index 9e197079..8af7ad8d 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/bot.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/bot.py
@@ -12,8 +12,15 @@ from nonebot.config import Config
from nonebot.typing import overrides
from nonebot.adapters import Bot as BaseBot
from nonebot.exception import ApiNotAvailable
-from nonebot.drivers import (Driver, WebSocket, HTTPResponse, ForwardDriver,
- ReverseDriver, HTTPConnection, WebSocketSetup)
+from nonebot.drivers import (
+ Driver,
+ WebSocket,
+ HTTPResponse,
+ ForwardDriver,
+ ReverseDriver,
+ HTTPConnection,
+ WebSocketSetup,
+)
from .config import Config as MiraiConfig
from .message import MessageChain, MessageSegment
@@ -23,16 +30,14 @@ from .utils import Log, process_event, argument_validation, catch_network_error
class SessionManager:
"""Bot会话管理器, 提供API主动调用接口"""
+
sessions: Dict[int, Tuple[str, httpx.AsyncClient]] = {}
def __init__(self, session_key: str, client: httpx.AsyncClient):
self.session_key, self.client = session_key, client
@catch_network_error
- async def post(self,
- path: str,
- *,
- params: Optional[Dict[str, Any]] = None) -> Any:
+ async def post(self, path: str, *, params: Optional[Dict[str, Any]] = None) -> Any:
"""
:说明:
@@ -51,7 +56,7 @@ class SessionManager:
path,
json={
**(params or {}),
- 'sessionKey': self.session_key,
+ "sessionKey": self.session_key,
},
timeout=3,
)
@@ -59,10 +64,9 @@ class SessionManager:
return response.json()
@catch_network_error
- async def request(self,
- path: str,
- *,
- params: Optional[Dict[str, Any]] = None) -> Any:
+ async def request(
+ self, path: str, *, params: Optional[Dict[str, Any]] = None
+ ) -> Any:
"""
:说明:
@@ -77,7 +81,7 @@ class SessionManager:
path,
params={
**(params or {}),
- 'sessionKey': self.session_key,
+ "sessionKey": self.session_key,
},
timeout=3,
)
@@ -98,7 +102,7 @@ class SessionManager:
"""
files = {k: v for k, v in params.items() if isinstance(v, BytesIO)}
form = {k: v for k, v in params.items() if k not in files}
- form['sessionKey'] = self.session_key
+ form["sessionKey"] = self.session_key
response = await self.client.post(
path,
data=form,
@@ -109,25 +113,25 @@ class SessionManager:
return response.json()
@classmethod
- async def new(cls, self_id: int, *, host: IPv4Address, port: int,
- auth_key: str) -> "SessionManager":
+ async def new(
+ cls, self_id: int, *, host: IPv4Address, port: int, auth_key: str
+ ) -> "SessionManager":
session = cls.get(self_id)
if session is not None:
return session
- client = httpx.AsyncClient(base_url=f'http://{host}:{port}',
- follow_redirects=True)
- response = await client.post('/auth', json={'authKey': auth_key})
+ client = httpx.AsyncClient(
+ base_url=f"http://{host}:{port}", follow_redirects=True
+ )
+ response = await client.post("/auth", json={"authKey": auth_key})
response.raise_for_status()
auth = response.json()
- assert auth['code'] == 0
- session_key = auth['session']
- response = await client.post('/verify',
- json={
- 'sessionKey': session_key,
- 'qq': self_id
- })
- assert response.json()['code'] == 0
+ assert auth["code"] == 0
+ session_key = auth["session"]
+ response = await client.post(
+ "/verify", json={"sessionKey": session_key, "qq": self_id}
+ )
+ assert response.json()["code"] == 0
cls.sessions[self_id] = session_key, client
return cls(session_key, client)
@@ -152,7 +156,7 @@ class Bot(BaseBot):
"""
- _type = 'mirai'
+ _type = "mirai"
@property
@overrides(BaseBot)
@@ -166,37 +170,42 @@ class Bot(BaseBot):
if api is None:
if isinstance(self.request, WebSocket):
asyncio.create_task(self.request.close(1000))
- assert api is not None, 'SessionManager has not been initialized'
+ assert api is not None, "SessionManager has not been initialized"
return api
@classmethod
@overrides(BaseBot)
async def check_permission(
- cls, driver: Driver,
- request: HTTPConnection) -> Tuple[Optional[str], HTTPResponse]:
+ cls, driver: Driver, request: HTTPConnection
+ ) -> Tuple[Optional[str], HTTPResponse]:
if isinstance(request, WebSocket):
- return None, HTTPResponse(
- 501, b'Websocket connection is not implemented')
- self_id: Optional[str] = request.headers.get('bot')
+ return None, HTTPResponse(501, b"Websocket connection is not implemented")
+ self_id: Optional[str] = request.headers.get("bot")
if self_id is None:
- return None, HTTPResponse(400, b'Header `Bot` is required.')
+ return None, HTTPResponse(400, b"Header `Bot` is required.")
self_id = str(self_id).strip()
await SessionManager.new(
int(self_id),
host=cls.mirai_config.host, # type: ignore
- port=cls.mirai_config.port, #type: ignore
- auth_key=cls.mirai_config.auth_key) # type: ignore
- return self_id, HTTPResponse(204, b'')
+ port=cls.mirai_config.port, # type: ignore
+ auth_key=cls.mirai_config.auth_key, # type: ignore
+ )
+ return self_id, HTTPResponse(204, b"")
@classmethod
@overrides(BaseBot)
- def register(cls,
- driver: Driver,
- config: "Config",
- qq: Optional[Union[int, List[int]]] = None):
+ def register(
+ cls,
+ driver: Driver,
+ config: "Config",
+ qq: Optional[Union[int, List[int]]] = None,
+ ):
cls.mirai_config = MiraiConfig(**config.dict())
- if (cls.mirai_config.auth_key and cls.mirai_config.host and
- cls.mirai_config.port) is None:
+ if (
+ cls.mirai_config.auth_key
+ and cls.mirai_config.host
+ and cls.mirai_config.port
+ ) is None:
raise ApiNotAvailable(cls._type)
super().register(driver, config)
@@ -209,17 +218,25 @@ class Bot(BaseBot):
self_ids = [qq] if isinstance(qq, int) else qq
async def url_factory(qq: int):
- assert cls.mirai_config.host and cls.mirai_config.port and cls.mirai_config.auth_key
+ assert (
+ cls.mirai_config.host
+ and cls.mirai_config.port
+ and cls.mirai_config.auth_key
+ )
session = await SessionManager.new(
qq,
host=cls.mirai_config.host,
port=cls.mirai_config.port,
- auth_key=cls.mirai_config.auth_key)
+ auth_key=cls.mirai_config.auth_key,
+ )
return WebSocketSetup(
adapter=cls._type,
self_id=str(qq),
- url=(f'ws://{cls.mirai_config.host}:{cls.mirai_config.port}'
- f'/all?sessionKey={session.session_key}'))
+ url=(
+ f"ws://{cls.mirai_config.host}:{cls.mirai_config.port}"
+ f"/all?sessionKey={session.session_key}"
+ ),
+ )
for self_id in self_ids:
driver.setup_websocket(partial(url_factory, qq=self_id))
@@ -234,13 +251,15 @@ class Bot(BaseBot):
try:
await process_event(
bot=self,
- event=Event.new({
- **json.loads(message),
- 'self_id': self.self_id,
- }),
+ event=Event.new(
+ {
+ **json.loads(message),
+ "self_id": self.self_id,
+ }
+ ),
)
except Exception as e:
- Log.error(f'Failed to handle message: {message}', e)
+ Log.error(f"Failed to handle message: {message}", e)
@overrides(BaseBot)
async def _call_api(self, api: str, **data) -> NoReturn:
@@ -266,10 +285,12 @@ class Bot(BaseBot):
@overrides(BaseBot)
@argument_validation
- async def send(self,
- event: Event,
- message: Union[MessageChain, MessageSegment, str],
- at_sender: bool = False):
+ async def send(
+ self,
+ event: Event,
+ message: Union[MessageChain, MessageSegment, str],
+ at_sender: bool = False,
+ ):
"""
:说明:
@@ -284,23 +305,24 @@ class Bot(BaseBot):
if not isinstance(message, MessageChain):
message = MessageChain(message)
if isinstance(event, FriendMessage):
- return await self.send_friend_message(target=event.sender.id,
- message_chain=message)
+ return await self.send_friend_message(
+ target=event.sender.id, message_chain=message
+ )
elif isinstance(event, GroupMessage):
if at_sender:
message = MessageSegment.at(event.sender.id) + message
- return await self.send_group_message(group=event.sender.group.id,
- message_chain=message)
+ return await self.send_group_message(
+ group=event.sender.group.id, message_chain=message
+ )
elif isinstance(event, TempMessage):
- return await self.send_temp_message(qq=event.sender.id,
- group=event.sender.group.id,
- message_chain=message)
+ return await self.send_temp_message(
+ qq=event.sender.id, group=event.sender.group.id, message_chain=message
+ )
else:
- raise ValueError(f'Unsupported event type {event!r}.')
+ raise ValueError(f"Unsupported event type {event!r}.")
@argument_validation
- async def send_friend_message(self, target: int,
- message_chain: MessageChain):
+ async def send_friend_message(self, target: int, message_chain: MessageChain):
"""
:说明:
@@ -311,15 +333,13 @@ class Bot(BaseBot):
* ``target: int``: 发送消息目标好友的 QQ 号
* ``message_chain: MessageChain``: 消息链,是一个消息对象构成的数组
"""
- return await self.api.post('sendFriendMessage',
- params={
- 'target': target,
- 'messageChain': message_chain.export()
- })
+ return await self.api.post(
+ "sendFriendMessage",
+ params={"target": target, "messageChain": message_chain.export()},
+ )
@argument_validation
- async def send_temp_message(self, qq: int, group: int,
- message_chain: MessageChain):
+ async def send_temp_message(self, qq: int, group: int, message_chain: MessageChain):
"""
:说明:
@@ -331,18 +351,15 @@ class Bot(BaseBot):
* ``group: int``: 临时会话群号
* ``message_chain: MessageChain``: 消息链,是一个消息对象构成的数组
"""
- return await self.api.post('sendTempMessage',
- params={
- 'qq': qq,
- 'group': group,
- 'messageChain': message_chain.export()
- })
+ return await self.api.post(
+ "sendTempMessage",
+ params={"qq": qq, "group": group, "messageChain": message_chain.export()},
+ )
@argument_validation
- async def send_group_message(self,
- group: int,
- message_chain: MessageChain,
- quote: Optional[int] = None):
+ async def send_group_message(
+ self, group: int, message_chain: MessageChain, quote: Optional[int] = None
+ ):
"""
:说明:
@@ -354,12 +371,14 @@ class Bot(BaseBot):
* ``message_chain: MessageChain``: 消息链,是一个消息对象构成的数组
* ``quote: Optional[int]``: 引用一条消息的 message_id 进行回复
"""
- return await self.api.post('sendGroupMessage',
- params={
- 'group': group,
- 'messageChain': message_chain.export(),
- 'quote': quote
- })
+ return await self.api.post(
+ "sendGroupMessage",
+ params={
+ "group": group,
+ "messageChain": message_chain.export(),
+ "quote": quote,
+ },
+ )
@argument_validation
async def recall(self, target: int):
@@ -372,11 +391,12 @@ class Bot(BaseBot):
* ``target: int``: 需要撤回的消息的message_id
"""
- return await self.api.post('recall', params={'target': target})
+ return await self.api.post("recall", params={"target": target})
@argument_validation
- async def send_image_message(self, target: int, qq: int, group: int,
- urls: List[str]) -> List[str]:
+ async def send_image_message(
+ self, target: int, qq: int, group: int, urls: List[str]
+ ) -> List[str]:
"""
:说明:
@@ -396,13 +416,10 @@ class Bot(BaseBot):
- ``List[str]``: 一个包含图片imageId的数组
"""
- return await self.api.post('sendImageMessage',
- params={
- 'target': target,
- 'qq': qq,
- 'group': group,
- 'urls': urls
- })
+ return await self.api.post(
+ "sendImageMessage",
+ params={"target": target, "qq": qq, "group": group, "urls": urls},
+ )
@argument_validation
async def upload_image(self, type: str, img: BytesIO):
@@ -416,11 +433,7 @@ class Bot(BaseBot):
* ``type: str``: "friend" 或 "group" 或 "temp"
* ``img: BytesIO``: 图片的BytesIO对象
"""
- return await self.api.upload('uploadImage',
- params={
- 'type': type,
- 'img': img
- })
+ return await self.api.upload("uploadImage", params={"type": type, "img": img})
@argument_validation
async def upload_voice(self, type: str, voice: BytesIO):
@@ -434,11 +447,9 @@ class Bot(BaseBot):
* ``type: str``: 当前仅支持 "group"
* ``voice: BytesIO``: 语音的BytesIO对象
"""
- return await self.api.upload('uploadVoice',
- params={
- 'type': type,
- 'voice': voice
- })
+ return await self.api.upload(
+ "uploadVoice", params={"type": type, "voice": voice}
+ )
@argument_validation
async def fetch_message(self, count: int = 10):
@@ -452,7 +463,7 @@ class Bot(BaseBot):
* ``count: int``: 获取消息和事件的数量
"""
- return await self.api.request('fetchMessage', params={'count': count})
+ return await self.api.request("fetchMessage", params={"count": count})
@argument_validation
async def fetch_latest_message(self, count: int = 10):
@@ -466,8 +477,7 @@ class Bot(BaseBot):
* ``count: int``: 获取消息和事件的数量
"""
- return await self.api.request('fetchLatestMessage',
- params={'count': count})
+ return await self.api.request("fetchLatestMessage", params={"count": count})
@argument_validation
async def peek_message(self, count: int = 10):
@@ -481,7 +491,7 @@ class Bot(BaseBot):
* ``count: int``: 获取消息和事件的数量
"""
- return await self.api.request('peekMessage', params={'count': count})
+ return await self.api.request("peekMessage", params={"count": count})
@argument_validation
async def peek_latest_message(self, count: int = 10):
@@ -495,8 +505,7 @@ class Bot(BaseBot):
* ``count: int``: 获取消息和事件的数量
"""
- return await self.api.request('peekLatestMessage',
- params={'count': count})
+ return await self.api.request("peekLatestMessage", params={"count": count})
@argument_validation
async def messsage_from_id(self, id: int):
@@ -510,7 +519,7 @@ class Bot(BaseBot):
* ``id: int``: 获取消息的message_id
"""
- return await self.api.request('messageFromId', params={'id': id})
+ return await self.api.request("messageFromId", params={"id": id})
@argument_validation
async def count_message(self):
@@ -519,7 +528,7 @@ class Bot(BaseBot):
使用此方法获取bot接收并缓存的消息总数,注意不包含被删除的
"""
- return await self.api.request('countMessage')
+ return await self.api.request("countMessage")
@argument_validation
async def friend_list(self) -> List[Dict[str, Any]]:
@@ -532,7 +541,7 @@ class Bot(BaseBot):
- ``List[Dict[str, Any]]``: 返回的好友列表数据
"""
- return await self.api.request('friendList')
+ return await self.api.request("friendList")
@argument_validation
async def group_list(self) -> List[Dict[str, Any]]:
@@ -545,7 +554,7 @@ class Bot(BaseBot):
- ``List[Dict[str, Any]]``: 返回的群列表数据
"""
- return await self.api.request('groupList')
+ return await self.api.request("groupList")
@argument_validation
async def member_list(self, target: int) -> List[Dict[str, Any]]:
@@ -562,7 +571,7 @@ class Bot(BaseBot):
- ``List[Dict[str, Any]]``: 返回的群成员列表数据
"""
- return await self.api.request('memberList', params={'target': target})
+ return await self.api.request("memberList", params={"target": target})
@argument_validation
async def mute(self, target: int, member_id: int, time: int):
@@ -577,12 +586,9 @@ class Bot(BaseBot):
* ``member_id: int``: 指定群员QQ号
* ``time: int``: 禁言时长,单位为秒,最多30天
"""
- return await self.api.post('mute',
- params={
- 'target': target,
- 'memberId': member_id,
- 'time': time
- })
+ return await self.api.post(
+ "mute", params={"target": target, "memberId": member_id, "time": time}
+ )
@argument_validation
async def unmute(self, target: int, member_id: int):
@@ -596,11 +602,9 @@ class Bot(BaseBot):
* ``target: int``: 指定群的群号
* ``member_id: int``: 指定群员QQ号
"""
- return await self.api.post('unmute',
- params={
- 'target': target,
- 'memberId': member_id
- })
+ return await self.api.post(
+ "unmute", params={"target": target, "memberId": member_id}
+ )
@argument_validation
async def kick(self, target: int, member_id: int, msg: str):
@@ -615,12 +619,9 @@ class Bot(BaseBot):
* ``member_id: int``: 指定群员QQ号
* ``msg: str``: 信息
"""
- return await self.api.post('kick',
- params={
- 'target': target,
- 'memberId': member_id,
- 'msg': msg
- })
+ return await self.api.post(
+ "kick", params={"target": target, "memberId": member_id, "msg": msg}
+ )
@argument_validation
async def quit(self, target: int):
@@ -633,7 +634,7 @@ class Bot(BaseBot):
* ``target: int``: 退出的群号
"""
- return await self.api.post('quit', params={'target': target})
+ return await self.api.post("quit", params={"target": target})
@argument_validation
async def mute_all(self, target: int):
@@ -646,7 +647,7 @@ class Bot(BaseBot):
* ``target: int``: 指定群的群号
"""
- return await self.api.post('muteAll', params={'target': target})
+ return await self.api.post("muteAll", params={"target": target})
@argument_validation
async def unmute_all(self, target: int):
@@ -659,7 +660,7 @@ class Bot(BaseBot):
* ``target: int``: 指定群的群号
"""
- return await self.api.post('unmuteAll', params={'target': target})
+ return await self.api.post("unmuteAll", params={"target": target})
@argument_validation
async def group_config(self, target: int):
@@ -685,7 +686,7 @@ class Bot(BaseBot):
"anonymousChat": true
}
"""
- return await self.api.request('groupConfig', params={'target': target})
+ return await self.api.request("groupConfig", params={"target": target})
@argument_validation
async def modify_group_config(self, target: int, config: Dict[str, Any]):
@@ -699,11 +700,9 @@ class Bot(BaseBot):
* ``target: int``: 指定群的群号
* ``config: Dict[str, Any]``: 群设置, 格式见 ``group_config`` 的返回值
"""
- return await self.api.post('groupConfig',
- params={
- 'target': target,
- 'config': config
- })
+ return await self.api.post(
+ "groupConfig", params={"target": target, "config": config}
+ )
@argument_validation
async def member_info(self, target: int, member_id: int):
@@ -726,15 +725,14 @@ class Bot(BaseBot):
"specialTitle": "群头衔"
}
"""
- return await self.api.request('memberInfo',
- params={
- 'target': target,
- 'memberId': member_id
- })
+ return await self.api.request(
+ "memberInfo", params={"target": target, "memberId": member_id}
+ )
@argument_validation
- async def modify_member_info(self, target: int, member_id: int,
- info: Dict[str, Any]):
+ async def modify_member_info(
+ self, target: int, member_id: int, info: Dict[str, Any]
+ ):
"""
:说明:
@@ -746,9 +744,6 @@ class Bot(BaseBot):
* ``member_id: int``: 群员QQ号
* ``info: Dict[str, Any]``: 群员资料, 格式见 ``member_info`` 的返回值
"""
- return await self.api.post('memberInfo',
- params={
- 'target': target,
- 'memberId': member_id,
- 'info': info
- })
+ return await self.api.post(
+ "memberInfo", params={"target": target, "memberId": member_id, "info": info}
+ )
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/config.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/config.py
index 6783259f..241af2a3 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/config.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/config.py
@@ -1,7 +1,7 @@
-from ipaddress import IPv4Address
from typing import Optional
+from ipaddress import IPv4Address
-from pydantic import BaseModel, Extra, Field
+from pydantic import Extra, Field, BaseModel
class Config(BaseModel):
@@ -14,9 +14,10 @@ class Config(BaseModel):
- ``mirai_host``: mirai-api-http 的地址
- ``mirai_port``: mirai-api-http 的端口
"""
- auth_key: Optional[str] = Field(None, alias='mirai_auth_key')
- host: Optional[IPv4Address] = Field(None, alias='mirai_host')
- port: Optional[int] = Field(None, alias='mirai_port')
+
+ auth_key: Optional[str] = Field(None, alias="mirai_auth_key")
+ host: Optional[IPv4Address] = Field(None, alias="mirai_host")
+ port: Optional[int] = Field(None, alias="mirai_port")
class Config:
extra = Extra.ignore
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/__init__.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/__init__.py
index 78e5cba4..14e21c74 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/__init__.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/__init__.py
@@ -5,25 +5,56 @@ r"""
部分字段可能与文档在符号上不一致
\:\:\:
"""
-from .base import (Event, GroupChatInfo, GroupInfo, PrivateChatInfo,
- UserPermission)
-from .message import *
from .notice import *
+from .message import *
from .request import *
+from .base import (
+ Event,
+ GroupInfo,
+ GroupChatInfo,
+ UserPermission,
+ PrivateChatInfo,
+)
__all__ = [
- 'Event', 'GroupChatInfo', 'GroupInfo', 'PrivateChatInfo', 'UserPermission',
- 'MessageSource', 'MessageEvent', 'GroupMessage', 'FriendMessage',
- 'TempMessage', 'NoticeEvent', 'MuteEvent', 'BotMuteEvent', 'BotUnmuteEvent',
- 'MemberMuteEvent', 'MemberUnmuteEvent', 'BotJoinGroupEvent',
- 'BotLeaveEventActive', 'BotLeaveEventKick', 'MemberJoinEvent',
- 'MemberLeaveEventKick', 'MemberLeaveEventQuit', 'FriendRecallEvent',
- 'GroupRecallEvent', 'GroupStateChangeEvent', 'GroupNameChangeEvent',
- 'GroupEntranceAnnouncementChangeEvent', 'GroupMuteAllEvent',
- 'GroupAllowAnonymousChatEvent', 'GroupAllowConfessTalkEvent',
- 'GroupAllowMemberInviteEvent', 'MemberStateChangeEvent',
- 'MemberCardChangeEvent', 'MemberSpecialTitleChangeEvent',
- 'BotGroupPermissionChangeEvent', 'MemberPermissionChangeEvent',
- 'RequestEvent', 'NewFriendRequestEvent', 'MemberJoinRequestEvent',
- 'BotInvitedJoinGroupRequestEvent'
+ "Event",
+ "GroupChatInfo",
+ "GroupInfo",
+ "PrivateChatInfo",
+ "UserPermission",
+ "MessageSource",
+ "MessageEvent",
+ "GroupMessage",
+ "FriendMessage",
+ "TempMessage",
+ "NoticeEvent",
+ "MuteEvent",
+ "BotMuteEvent",
+ "BotUnmuteEvent",
+ "MemberMuteEvent",
+ "MemberUnmuteEvent",
+ "BotJoinGroupEvent",
+ "BotLeaveEventActive",
+ "BotLeaveEventKick",
+ "MemberJoinEvent",
+ "MemberLeaveEventKick",
+ "MemberLeaveEventQuit",
+ "FriendRecallEvent",
+ "GroupRecallEvent",
+ "GroupStateChangeEvent",
+ "GroupNameChangeEvent",
+ "GroupEntranceAnnouncementChangeEvent",
+ "GroupMuteAllEvent",
+ "GroupAllowAnonymousChatEvent",
+ "GroupAllowConfessTalkEvent",
+ "GroupAllowMemberInviteEvent",
+ "MemberStateChangeEvent",
+ "MemberCardChangeEvent",
+ "MemberSpecialTitleChangeEvent",
+ "BotGroupPermissionChangeEvent",
+ "MemberPermissionChangeEvent",
+ "RequestEvent",
+ "NewFriendRequestEvent",
+ "MemberJoinRequestEvent",
+ "BotInvitedJoinGroupRequestEvent",
]
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/base.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/base.py
index fd95f4e8..93b7863b 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/base.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/base.py
@@ -22,9 +22,10 @@ class UserPermission(str, Enum):
* ``ADMINISTRATOR``: 群管理
* ``MEMBER``: 普通群成员
"""
- OWNER = 'OWNER'
- ADMINISTRATOR = 'ADMINISTRATOR'
- MEMBER = 'MEMBER'
+
+ OWNER = "OWNER"
+ ADMINISTRATOR = "ADMINISTRATOR"
+ MEMBER = "MEMBER"
class NudgeSubjectKind(str, Enum):
@@ -36,8 +37,9 @@ class NudgeSubjectKind(str, Enum):
* ``Group``: 群
* ``Friend``: 好友
"""
- Group = 'Group'
- Friend = 'Friend'
+
+ Group = "Group"
+ Friend = "Friend"
class GroupInfo(BaseModel):
@@ -48,7 +50,7 @@ class GroupInfo(BaseModel):
class GroupChatInfo(BaseModel):
id: int
- name: str = Field(alias='memberName')
+ name: str = Field(alias="memberName")
permission: UserPermission
group: GroupInfo
@@ -71,6 +73,7 @@ class Event(BaseEvent):
.. _mirai-api-http 事件类型:
https://github.com/project-mirai/mirai-api-http/blob/master/docs/EventType.md
"""
+
self_id: int
type: str
@@ -79,11 +82,12 @@ class Event(BaseEvent):
"""
此事件类的工厂函数, 能够通过事件数据选择合适的子类进行序列化
"""
- type = data['type']
+ type = data["type"]
def all_subclasses(cls: Type[Event]):
return set(cls.__subclasses__()).union(
- [s for c in cls.__subclasses__() for s in all_subclasses(c)])
+ [s for c in cls.__subclasses__() for s in all_subclasses(c)]
+ )
event_class: Optional[Type[Event]] = None
for subclass in all_subclasses(cls):
@@ -99,23 +103,25 @@ class Event(BaseEvent):
return event_class.parse_obj(data)
except ValidationError as e:
logger.info(
- f'Failed to parse {data} to class {event_class.__name__}: '
- f'{e.errors()!r}. Fallback to parent class.')
+ f"Failed to parse {data} to class {event_class.__name__}: "
+ f"{e.errors()!r}. Fallback to parent class."
+ )
event_class = event_class.__base__ # type: ignore
- raise ValueError(f'Failed to serialize {data}.')
+ raise ValueError(f"Failed to serialize {data}.")
@overrides(BaseEvent)
def get_type(self) -> Literal["message", "notice", "request", "meta_event"]:
from . import meta, notice, message, request
+
if isinstance(self, message.MessageEvent):
- return 'message'
+ return "message"
elif isinstance(self, notice.NoticeEvent):
- return 'notice'
+ return "notice"
elif isinstance(self, request.RequestEvent):
- return 'request'
+ return "request"
else:
- return 'meta_event'
+ return "meta_event"
@overrides(BaseEvent)
def get_event_name(self) -> str:
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/message.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/message.py
index 5dda0857..74896eee 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/message.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/message.py
@@ -1,7 +1,7 @@
from datetime import datetime
from typing import Any, Optional
-from pydantic import BaseModel, Field
+from pydantic import Field, BaseModel
from nonebot.typing import overrides
@@ -16,7 +16,8 @@ class MessageSource(BaseModel):
class MessageEvent(Event):
"""消息事件基类"""
- message_chain: MessageChain = Field(alias='messageChain')
+
+ message_chain: MessageChain = Field(alias="messageChain")
source: Optional[MessageSource] = None
sender: Any
@@ -39,12 +40,13 @@ class MessageEvent(Event):
class GroupMessage(MessageEvent):
"""群消息事件"""
+
sender: GroupChatInfo
to_me: bool = False
@overrides(MessageEvent)
def get_session_id(self) -> str:
- return f'group_{self.sender.group.id}_' + self.get_user_id()
+ return f"group_{self.sender.group.id}_" + self.get_user_id()
@overrides(MessageEvent)
def get_user_id(self) -> str:
@@ -57,6 +59,7 @@ class GroupMessage(MessageEvent):
class FriendMessage(MessageEvent):
"""好友消息事件"""
+
sender: PrivateChatInfo
@overrides(MessageEvent)
@@ -65,7 +68,7 @@ class FriendMessage(MessageEvent):
@overrides(MessageEvent)
def get_session_id(self) -> str:
- return 'friend_' + self.get_user_id()
+ return "friend_" + self.get_user_id()
@overrides(MessageEvent)
def is_tome(self) -> bool:
@@ -74,11 +77,12 @@ class FriendMessage(MessageEvent):
class TempMessage(MessageEvent):
"""临时会话消息事件"""
+
sender: GroupChatInfo
@overrides(MessageEvent)
def get_session_id(self) -> str:
- return f'temp_{self.sender.group.id}_' + self.get_user_id()
+ return f"temp_{self.sender.group.id}_" + self.get_user_id()
@overrides(MessageEvent)
def is_tome(self) -> bool:
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/meta.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/meta.py
index e42baf72..c0fa7a29 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/meta.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/meta.py
@@ -3,29 +3,35 @@ from .base import Event
class MetaEvent(Event):
"""元事件基类"""
+
qq: int
class BotOnlineEvent(MetaEvent):
"""Bot登录成功"""
+
pass
class BotOfflineEventActive(MetaEvent):
"""Bot主动离线"""
+
pass
class BotOfflineEventForce(MetaEvent):
"""Bot被挤下线"""
+
pass
class BotOfflineEventDropped(MetaEvent):
"""Bot被服务器断开或因网络问题而掉线"""
+
pass
class BotReloginEvent(MetaEvent):
"""Bot主动重新登录"""
- pass
\ No newline at end of file
+
+ pass
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/notice.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/notice.py
index 8726d58e..0fa30dda 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/notice.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/notice.py
@@ -2,88 +2,103 @@ from typing import Any, Optional
from pydantic import Field
-from .base import Event, GroupChatInfo, GroupInfo, NudgeSubject, UserPermission
+from .base import Event, GroupInfo, NudgeSubject, GroupChatInfo, UserPermission
class NoticeEvent(Event):
"""通知事件基类"""
+
pass
class MuteEvent(NoticeEvent):
"""禁言类事件基类"""
+
operator: GroupChatInfo
class BotMuteEvent(MuteEvent):
"""Bot被禁言"""
+
pass
class BotUnmuteEvent(MuteEvent):
"""Bot被取消禁言"""
+
pass
class MemberMuteEvent(MuteEvent):
"""群成员被禁言事件(该成员不是Bot)"""
- duration_seconds: int = Field(alias='durationSeconds')
+
+ duration_seconds: int = Field(alias="durationSeconds")
member: GroupChatInfo
operator: Optional[GroupChatInfo] = None
class MemberUnmuteEvent(MuteEvent):
"""群成员被取消禁言事件(该成员不是Bot)"""
+
member: GroupChatInfo
operator: Optional[GroupChatInfo] = None
class BotJoinGroupEvent(NoticeEvent):
"""Bot加入了一个新群"""
+
group: GroupInfo
class BotLeaveEventActive(BotJoinGroupEvent):
"""Bot主动退出一个群"""
+
pass
class BotLeaveEventKick(BotJoinGroupEvent):
"""Bot被踢出一个群"""
+
pass
class MemberJoinEvent(NoticeEvent):
"""新人入群的事件"""
+
member: GroupChatInfo
class MemberLeaveEventKick(MemberJoinEvent):
"""成员被踢出群(该成员不是Bot)"""
+
operator: Optional[GroupChatInfo] = None
class MemberLeaveEventQuit(MemberJoinEvent):
"""成员主动离群(该成员不是Bot)"""
+
pass
class FriendRecallEvent(NoticeEvent):
"""好友消息撤回"""
- author_id: int = Field(alias='authorId')
- message_id: int = Field(alias='messageId')
+
+ author_id: int = Field(alias="authorId")
+ message_id: int = Field(alias="messageId")
time: int
operator: int
class GroupRecallEvent(FriendRecallEvent):
"""群消息撤回"""
+
group: GroupInfo
operator: Optional[GroupChatInfo] = None
class GroupStateChangeEvent(NoticeEvent):
"""群变化事件基类"""
+
origin: Any
current: Any
group: GroupInfo
@@ -92,73 +107,85 @@ class GroupStateChangeEvent(NoticeEvent):
class GroupNameChangeEvent(GroupStateChangeEvent):
"""某个群名改变"""
+
origin: str
current: str
class GroupEntranceAnnouncementChangeEvent(GroupStateChangeEvent):
"""某群入群公告改变"""
+
origin: str
current: str
class GroupMuteAllEvent(GroupStateChangeEvent):
"""全员禁言"""
+
origin: bool
current: bool
class GroupAllowAnonymousChatEvent(GroupStateChangeEvent):
"""匿名聊天"""
+
origin: bool
current: bool
class GroupAllowConfessTalkEvent(GroupStateChangeEvent):
"""坦白说"""
+
origin: bool
current: bool
class GroupAllowMemberInviteEvent(GroupStateChangeEvent):
"""允许群员邀请好友加群"""
+
origin: bool
current: bool
class MemberStateChangeEvent(NoticeEvent):
"""群成员变化事件基类"""
+
member: GroupChatInfo
operator: Optional[GroupChatInfo] = None
class MemberCardChangeEvent(MemberStateChangeEvent):
"""群名片改动"""
+
origin: str
current: str
class MemberSpecialTitleChangeEvent(MemberStateChangeEvent):
"""群头衔改动(只有群主有操作限权)"""
+
origin: str
current: str
class BotGroupPermissionChangeEvent(MemberStateChangeEvent):
"""Bot在群里的权限被改变"""
+
origin: UserPermission
current: UserPermission
class MemberPermissionChangeEvent(MemberStateChangeEvent):
"""成员权限改变的事件(该成员不是Bot)"""
+
origin: UserPermission
current: UserPermission
class NudgeEvent(NoticeEvent):
"""戳一戳触发事件"""
- from_id: int = Field(alias='fromId')
+
+ from_id: int = Field(alias="fromId")
target: int
subject: NudgeSubject
action: str
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/request.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/request.py
index d57af767..42f33e97 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/request.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/event/request.py
@@ -1,7 +1,7 @@
from typing import TYPE_CHECKING
+from typing_extensions import Literal
from pydantic import Field
-from typing_extensions import Literal
from .base import Event
@@ -11,15 +11,17 @@ if TYPE_CHECKING:
class RequestEvent(Event):
"""请求事件基类"""
- event_id: int = Field(alias='eventId')
+
+ event_id: int = Field(alias="eventId")
message: str
nick: str
class NewFriendRequestEvent(RequestEvent):
"""添加好友申请"""
- from_id: int = Field(alias='fromId')
- group_id: int = Field(0, alias='groupId')
+
+ from_id: int = Field(alias="fromId")
+ group_id: int = Field(0, alias="groupId")
async def approve(self, bot: "Bot"):
"""
@@ -31,19 +33,18 @@ class NewFriendRequestEvent(RequestEvent):
* ``bot: Bot``: 当前的 ``Bot`` 对象
"""
- return await bot.api.post('/resp/newFriendRequestEvent',
- params={
- 'eventId': self.event_id,
- 'groupId': self.group_id,
- 'fromId': self.from_id,
- 'operate': 0,
- 'message': ''
- })
+ return await bot.api.post(
+ "/resp/newFriendRequestEvent",
+ params={
+ "eventId": self.event_id,
+ "groupId": self.group_id,
+ "fromId": self.from_id,
+ "operate": 0,
+ "message": "",
+ },
+ )
- async def reject(self,
- bot: "Bot",
- operate: Literal[1, 2] = 1,
- message: str = ''):
+ async def reject(self, bot: "Bot", operate: Literal[1, 2] = 1, message: str = ""):
"""
:说明:
@@ -60,21 +61,24 @@ class NewFriendRequestEvent(RequestEvent):
* ``message: str``: 回复的信息
"""
assert operate > 0
- return await bot.api.post('/resp/newFriendRequestEvent',
- params={
- 'eventId': self.event_id,
- 'groupId': self.group_id,
- 'fromId': self.from_id,
- 'operate': operate,
- 'message': message
- })
+ return await bot.api.post(
+ "/resp/newFriendRequestEvent",
+ params={
+ "eventId": self.event_id,
+ "groupId": self.group_id,
+ "fromId": self.from_id,
+ "operate": operate,
+ "message": message,
+ },
+ )
class MemberJoinRequestEvent(RequestEvent):
"""用户入群申请(Bot需要有管理员权限)"""
- from_id: int = Field(alias='fromId')
- group_id: int = Field(alias='groupId')
- group_name: str = Field(alias='groupName')
+
+ from_id: int = Field(alias="fromId")
+ group_id: int = Field(alias="groupId")
+ group_name: str = Field(alias="groupName")
async def approve(self, bot: "Bot"):
"""
@@ -86,19 +90,20 @@ class MemberJoinRequestEvent(RequestEvent):
* ``bot: Bot``: 当前的 ``Bot`` 对象
"""
- return await bot.api.post('/resp/memberJoinRequestEvent',
- params={
- 'eventId': self.event_id,
- 'groupId': self.group_id,
- 'fromId': self.from_id,
- 'operate': 0,
- 'message': ''
- })
+ return await bot.api.post(
+ "/resp/memberJoinRequestEvent",
+ params={
+ "eventId": self.event_id,
+ "groupId": self.group_id,
+ "fromId": self.from_id,
+ "operate": 0,
+ "message": "",
+ },
+ )
- async def reject(self,
- bot: "Bot",
- operate: Literal[1, 2, 3, 4] = 1,
- message: str = ''):
+ async def reject(
+ self, bot: "Bot", operate: Literal[1, 2, 3, 4] = 1, message: str = ""
+ ):
"""
:说明:
@@ -117,21 +122,24 @@ class MemberJoinRequestEvent(RequestEvent):
* ``message: str``: 回复的信息
"""
assert operate > 0
- return await bot.api.post('/resp/memberJoinRequestEvent',
- params={
- 'eventId': self.event_id,
- 'groupId': self.group_id,
- 'fromId': self.from_id,
- 'operate': operate,
- 'message': message
- })
+ return await bot.api.post(
+ "/resp/memberJoinRequestEvent",
+ params={
+ "eventId": self.event_id,
+ "groupId": self.group_id,
+ "fromId": self.from_id,
+ "operate": operate,
+ "message": message,
+ },
+ )
class BotInvitedJoinGroupRequestEvent(RequestEvent):
"""Bot被邀请入群申请"""
- from_id: int = Field(alias='fromId')
- group_id: int = Field(alias='groupId')
- group_name: str = Field(alias='groupName')
+
+ from_id: int = Field(alias="fromId")
+ group_id: int = Field(alias="groupId")
+ group_name: str = Field(alias="groupName")
async def approve(self, bot: "Bot"):
"""
@@ -143,14 +151,16 @@ class BotInvitedJoinGroupRequestEvent(RequestEvent):
* ``bot: Bot``: 当前的 ``Bot`` 对象
"""
- return await bot.api.post('/resp/botInvitedJoinGroupRequestEvent',
- params={
- 'eventId': self.event_id,
- 'groupId': self.group_id,
- 'fromId': self.from_id,
- 'operate': 0,
- 'message': ''
- })
+ return await bot.api.post(
+ "/resp/botInvitedJoinGroupRequestEvent",
+ params={
+ "eventId": self.event_id,
+ "groupId": self.group_id,
+ "fromId": self.from_id,
+ "operate": 0,
+ "message": "",
+ },
+ )
async def reject(self, bot: "Bot", message: str = ""):
"""
@@ -163,11 +173,13 @@ class BotInvitedJoinGroupRequestEvent(RequestEvent):
* ``bot: Bot``: 当前的 ``Bot`` 对象
* ``message: str``: 邀请消息
"""
- return await bot.api.post('/resp/botInvitedJoinGroupRequestEvent',
- params={
- 'eventId': self.event_id,
- 'groupId': self.group_id,
- 'fromId': self.from_id,
- 'operate': 1,
- 'message': message
- })
+ return await bot.api.post(
+ "/resp/botInvitedJoinGroupRequestEvent",
+ params={
+ "eventId": self.event_id,
+ "groupId": self.group_id,
+ "fromId": self.from_id,
+ "operate": 1,
+ "message": message,
+ },
+ )
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/message.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/message.py
index 14d6f9e8..2f74b197 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/message.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/message.py
@@ -1,28 +1,29 @@
from enum import Enum
-from typing import Any, List, Dict, Type, Iterable, Optional, Union
+from typing import Any, Dict, List, Type, Union, Iterable, Optional
from pydantic import validate_arguments
+from nonebot.typing import overrides
from nonebot.adapters import Message as BaseMessage
from nonebot.adapters import MessageSegment as BaseMessageSegment
-from nonebot.typing import overrides
class MessageType(str, Enum):
"""消息类型枚举类"""
- SOURCE = 'Source'
- QUOTE = 'Quote'
- AT = 'At'
- AT_ALL = 'AtAll'
- FACE = 'Face'
- PLAIN = 'Plain'
- IMAGE = 'Image'
- FLASH_IMAGE = 'FlashImage'
- VOICE = 'Voice'
- XML = 'Xml'
- JSON = 'Json'
- APP = 'App'
- POKE = 'Poke'
+
+ SOURCE = "Source"
+ QUOTE = "Quote"
+ AT = "At"
+ AT_ALL = "AtAll"
+ FACE = "Face"
+ PLAIN = "Plain"
+ IMAGE = "Image"
+ FLASH_IMAGE = "FlashImage"
+ VOICE = "Voice"
+ XML = "Xml"
+ JSON = "Json"
+ APP = "App"
+ POKE = "Poke"
class MessageSegment(BaseMessageSegment["MessageChain"]):
@@ -43,21 +44,24 @@ class MessageSegment(BaseMessageSegment["MessageChain"]):
@validate_arguments
@overrides(BaseMessageSegment)
def __init__(self, type: MessageType, **data: Any):
- super().__init__(type=type,
- data={k: v for k, v in data.items() if v is not None})
+ super().__init__(
+ type=type, data={k: v for k, v in data.items() if v is not None}
+ )
@overrides(BaseMessageSegment)
def __str__(self) -> str:
- return self.data['text'] if self.is_text() else repr(self)
+ return self.data["text"] if self.is_text() else repr(self)
def __repr__(self) -> str:
- return '[mirai:%s]' % ','.join([
- self.type.value,
- *map(
- lambda s: '%s=%r' % s,
- self.data.items(),
- ),
- ])
+ return "[mirai:%s]" % ",".join(
+ [
+ self.type.value,
+ *map(
+ lambda s: "%s=%r" % s,
+ self.data.items(),
+ ),
+ ]
+ )
@overrides(BaseMessageSegment)
def is_text(self) -> bool:
@@ -65,15 +69,21 @@ class MessageSegment(BaseMessageSegment["MessageChain"]):
def as_dict(self) -> Dict[str, Any]:
"""导出可以被正常json序列化的结构体"""
- return {'type': self.type.value, **self.data}
+ return {"type": self.type.value, **self.data}
@classmethod
def source(cls, id: int, time: int):
return cls(type=MessageType.SOURCE, id=id, time=time)
@classmethod
- def quote(cls, id: int, group_id: int, sender_id: int, target_id: int,
- origin: "MessageChain"):
+ def quote(
+ cls,
+ id: int,
+ group_id: int,
+ sender_id: int,
+ target_id: int,
+ origin: "MessageChain",
+ ):
"""
:说明:
@@ -87,12 +97,14 @@ class MessageSegment(BaseMessageSegment["MessageChain"]):
* ``target_id: int``: 被引用回复的原消息的接收者者的QQ号(或群号)
* ``origin: MessageChain``: 被引用回复的原消息的消息链对象
"""
- return cls(type=MessageType.QUOTE,
- id=id,
- groupId=group_id,
- senderId=sender_id,
- targetId=target_id,
- origin=origin.export())
+ return cls(
+ type=MessageType.QUOTE,
+ id=id,
+ groupId=group_id,
+ senderId=sender_id,
+ targetId=target_id,
+ origin=origin.export(),
+ )
@classmethod
def at(cls, target: int):
@@ -144,10 +156,12 @@ class MessageSegment(BaseMessageSegment["MessageChain"]):
return cls(type=MessageType.PLAIN, text=text)
@classmethod
- def image(cls,
- image_id: Optional[str] = None,
- url: Optional[str] = None,
- path: Optional[str] = None):
+ def image(
+ cls,
+ image_id: Optional[str] = None,
+ url: Optional[str] = None,
+ path: Optional[str] = None,
+ ):
"""
:说明:
@@ -162,10 +176,12 @@ class MessageSegment(BaseMessageSegment["MessageChain"]):
return cls(type=MessageType.IMAGE, imageId=image_id, url=url, path=path)
@classmethod
- def flash_image(cls,
- image_id: Optional[str] = None,
- url: Optional[str] = None,
- path: Optional[str] = None):
+ def flash_image(
+ cls,
+ image_id: Optional[str] = None,
+ url: Optional[str] = None,
+ path: Optional[str] = None,
+ ):
"""
:说明:
@@ -175,16 +191,15 @@ class MessageSegment(BaseMessageSegment["MessageChain"]):
同 ``image``
"""
- return cls(type=MessageType.FLASH_IMAGE,
- imageId=image_id,
- url=url,
- path=path)
+ return cls(type=MessageType.FLASH_IMAGE, imageId=image_id, url=url, path=path)
@classmethod
- def voice(cls,
- voice_id: Optional[str] = None,
- url: Optional[str] = None,
- path: Optional[str] = None):
+ def voice(
+ cls,
+ voice_id: Optional[str] = None,
+ url: Optional[str] = None,
+ path: Optional[str] = None,
+ ):
"""
:说明:
@@ -196,10 +211,7 @@ class MessageSegment(BaseMessageSegment["MessageChain"]):
* ``url: Optional[str]``: 语音的URL,发送时可作网络语音的链接
* ``path: Optional[str]``: 语音的路径,发送本地语音
"""
- return cls(type=MessageType.FLASH_IMAGE,
- imageId=voice_id,
- url=url,
- path=path)
+ return cls(type=MessageType.FLASH_IMAGE, imageId=voice_id, url=url, path=path)
@classmethod
def xml(cls, xml: str):
@@ -282,16 +294,14 @@ class MessageChain(BaseMessage[MessageSegment]):
return [MessageSegment.plain(text=message)]
return [
*map(
- lambda x: x
- if isinstance(x, MessageSegment) else MessageSegment(**x),
- message)
+ lambda x: x if isinstance(x, MessageSegment) else MessageSegment(**x),
+ message,
+ )
]
def export(self) -> List[Dict[str, Any]]:
"""导出为可以被正常json序列化的数组"""
- return [
- *map(lambda segment: segment.as_dict(), self.copy()) # type: ignore
- ]
+ return [*map(lambda segment: segment.as_dict(), self.copy())] # type: ignore
def extract_first(self, *type: MessageType) -> Optional[MessageSegment]:
"""
@@ -311,4 +321,4 @@ class MessageChain(BaseMessage[MessageSegment]):
return None
def __repr__(self) -> str:
- return f'<{self.__class__.__name__} {[*self.copy()]}>'
+ return f"<{self.__class__.__name__} {[*self.copy()]}>"
diff --git a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/utils.py b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/utils.py
index 200f0197..6a403990 100644
--- a/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/utils.py
+++ b/packages/nonebot-adapter-mirai/nonebot/adapters/mirai/utils.py
@@ -1,17 +1,17 @@
import re
from functools import wraps
-from typing import TYPE_CHECKING, Any, Callable, Coroutine, Optional, TypeVar
+from typing import TYPE_CHECKING, Any, TypeVar, Callable, Optional, Coroutine
import httpx
from pydantic import Extra, ValidationError, validate_arguments
-import nonebot.exception as exception
from nonebot.log import logger
+import nonebot.exception as exception
from nonebot.message import handle_event
from nonebot.utils import escape_tag, logger_wrapper
-from .event import Event, GroupMessage, MessageEvent, MessageSource
from .message import MessageType, MessageSegment
+from .event import Event, GroupMessage, MessageEvent, MessageSource
if TYPE_CHECKING:
from .bot import Bot
@@ -21,28 +21,27 @@ _AnyCallable = TypeVar("_AnyCallable", bound=Callable)
class Log:
-
@staticmethod
def log(level: str, message: str, exception: Optional[Exception] = None):
- logger = logger_wrapper('MIRAI')
- message = '' + escape_tag(message) + ''
+ logger = logger_wrapper("MIRAI")
+ message = "" + escape_tag(message) + ""
logger(level=level.upper(), message=message, exception=exception)
@classmethod
def info(cls, message: Any):
- cls.log('INFO', str(message))
+ cls.log("INFO", str(message))
@classmethod
def debug(cls, message: Any):
- cls.log('DEBUG', str(message))
+ cls.log("DEBUG", str(message))
@classmethod
def warn(cls, message: Any):
- cls.log('WARNING', str(message))
+ cls.log("WARNING", str(message))
@classmethod
def error(cls, message: Any, exception: Optional[Exception] = None):
- cls.log('ERROR', str(message), exception=exception)
+ cls.log("ERROR", str(message), exception=exception)
class ActionFailed(exception.ActionFailed):
@@ -53,12 +52,13 @@ class ActionFailed(exception.ActionFailed):
"""
def __init__(self, **kwargs):
- super().__init__('mirai')
+ super().__init__("mirai")
self.data = kwargs.copy()
def __repr__(self):
- return self.__class__.__name__ + '(%s)' % ', '.join(
- map(lambda m: '%s=%r' % m, self.data.items()))
+ return self.__class__.__name__ + "(%s)" % ", ".join(
+ map(lambda m: "%s=%r" % m, self.data.items())
+ )
class InvalidArgument(exception.AdapterException):
@@ -69,7 +69,7 @@ class InvalidArgument(exception.AdapterException):
"""
def __init__(self, **kwargs):
- super().__init__('mirai')
+ super().__init__("mirai")
def catch_network_error(function: _AsyncCallable) -> _AsyncCallable:
@@ -90,11 +90,12 @@ def catch_network_error(function: _AsyncCallable) -> _AsyncCallable:
try:
data = await function(*args, **kwargs)
except httpx.HTTPError:
- raise exception.NetworkError('mirai')
- logger.opt(colors=True).debug('Mirai API returned data: '
- f'{escape_tag(str(data))}')
+ raise exception.NetworkError("mirai")
+ logger.opt(colors=True).debug(
+ "Mirai API returned data: " f"{escape_tag(str(data))}"
+ )
if isinstance(data, dict):
- if data.get('code', 0) != 0:
+ if data.get("code", 0) != 0:
raise ActionFailed(**data)
return data
@@ -109,10 +110,9 @@ def argument_validation(function: _AnyCallable) -> _AnyCallable:
会在参数出错时释放 ``InvalidArgument`` 异常
"""
- function = validate_arguments(config={
- 'arbitrary_types_allowed': True,
- 'extra': Extra.forbid
- })(function)
+ function = validate_arguments(
+ config={"arbitrary_types_allowed": True, "extra": Extra.forbid}
+ )(function)
@wraps(function)
def wrapper(*args, **kwargs):
@@ -134,12 +134,12 @@ def process_source(bot: "Bot", event: MessageEvent) -> MessageEvent:
def process_at(bot: "Bot", event: GroupMessage) -> GroupMessage:
at = event.message_chain.extract_first(MessageType.AT)
if at is not None:
- if at.data['target'] == event.self_id:
+ if at.data["target"] == event.self_id:
event.to_me = True
else:
event.message_chain.insert(0, at)
if not event.message_chain:
- event.message_chain.append(MessageSegment.plain(''))
+ event.message_chain.append(MessageSegment.plain(""))
return event
@@ -147,13 +147,13 @@ def process_nick(bot: "Bot", event: GroupMessage) -> GroupMessage:
plain = event.message_chain.extract_first(MessageType.PLAIN)
if plain is not None:
text = str(plain)
- nick_regex = '|'.join(filter(lambda x: x, bot.config.nickname))
+ nick_regex = "|".join(filter(lambda x: x, bot.config.nickname))
matched = re.search(rf"^({nick_regex})([\s,,]*|$)", text, re.IGNORECASE)
if matched is not None:
event.to_me = True
nickname = matched.group(1)
- Log.info(f'User is calling me {nickname}')
- plain.data['text'] = text[matched.end():]
+ Log.info(f"User is calling me {nickname}")
+ plain.data["text"] = text[matched.end() :]
event.message_chain.insert(0, plain)
return event
@@ -161,7 +161,7 @@ def process_nick(bot: "Bot", event: GroupMessage) -> GroupMessage:
def process_reply(bot: "Bot", event: GroupMessage) -> GroupMessage:
reply = event.message_chain.extract_first(MessageType.QUOTE)
if reply is not None:
- if reply.data['senderId'] == event.self_id:
+ if reply.data["senderId"] == event.self_id:
event.to_me = True
else:
event.message_chain.insert(0, reply)
diff --git a/packages/nonebot-adapter-mirai/pyproject.toml b/packages/nonebot-adapter-mirai/pyproject.toml
index 7340cd75..7f3c5380 100644
--- a/packages/nonebot-adapter-mirai/pyproject.toml
+++ b/packages/nonebot-adapter-mirai/pyproject.toml
@@ -34,6 +34,21 @@ nonebot2 = { path = "../../", develop = true }
# url = "https://mirrors.aliyun.com/pypi/simple/"
# default = true
+[tool.black]
+line-length = 88
+target-version = ["py37", "py38", "py39"]
+include = '\.pyi?$'
+extend-exclude = '''
+'''
+
+[tool.isort]
+profile = "black"
+line_length = 80
+length_sort = true
+skip_gitignore = true
+force_sort_within_sections = true
+extra_standard_library = ["typing_extensions"]
+
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
diff --git a/packages/nonebot-plugin-docs/nonebot_plugin_docs/__init__.py b/packages/nonebot-plugin-docs/nonebot_plugin_docs/__init__.py
index 161cd626..98a40f8c 100644
--- a/packages/nonebot-plugin-docs/nonebot_plugin_docs/__init__.py
+++ b/packages/nonebot-plugin-docs/nonebot_plugin_docs/__init__.py
@@ -7,8 +7,7 @@ from nonebot.log import logger
def init():
driver = nonebot.get_driver()
try:
- _module = importlib.import_module(
- f"nonebot_plugin_docs.drivers.{driver.type}")
+ _module = importlib.import_module(f"nonebot_plugin_docs.drivers.{driver.type}")
except ImportError:
logger.warning(f"Driver {driver.type} not supported")
return
@@ -18,8 +17,9 @@ def init():
port = driver.config.port
if host in ["0.0.0.0", "127.0.0.1"]:
host = "localhost"
- logger.opt(colors=True).info(f"Nonebot docs will be running at: "
- f"http://{host}:{port}/docs/")
+ logger.opt(colors=True).info(
+ f"Nonebot docs will be running at: " f"http://{host}:{port}/docs/"
+ )
init()
diff --git a/packages/nonebot-plugin-docs/nonebot_plugin_docs/drivers/fastapi.py b/packages/nonebot-plugin-docs/nonebot_plugin_docs/drivers/fastapi.py
index da598d19..c01cbd09 100644
--- a/packages/nonebot-plugin-docs/nonebot_plugin_docs/drivers/fastapi.py
+++ b/packages/nonebot-plugin-docs/nonebot_plugin_docs/drivers/fastapi.py
@@ -9,6 +9,4 @@ def register_route(driver: Driver):
static_path = str((Path(__file__).parent / ".." / "dist").resolve())
- app.mount("/docs",
- StaticFiles(directory=static_path, html=True),
- name="docs")
+ app.mount("/docs", StaticFiles(directory=static_path, html=True), name="docs")
diff --git a/packages/nonebot-plugin-docs/pyproject.toml b/packages/nonebot-plugin-docs/pyproject.toml
index ce5c9d18..8ee81dc6 100644
--- a/packages/nonebot-plugin-docs/pyproject.toml
+++ b/packages/nonebot-plugin-docs/pyproject.toml
@@ -18,6 +18,21 @@ nonebot2 = "^2.0.0-alpha.1"
[tool.poetry.dev-dependencies]
+[tool.black]
+line-length = 88
+target-version = ["py37", "py38", "py39"]
+include = '\.pyi?$'
+extend-exclude = '''
+'''
+
+[tool.isort]
+profile = "black"
+line_length = 80
+length_sort = true
+skip_gitignore = true
+force_sort_within_sections = true
+extra_standard_library = ["typing_extensions"]
+
[build-system]
requires = ["poetry-core>=1.0.0"]
build-backend = "poetry.core.masonry.api"
diff --git a/poetry.lock b/poetry.lock
index b3568e16..56535b06 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -151,6 +151,34 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
[package.dependencies]
pytz = ">=2015.7"
+[[package]]
+name = "black"
+version = "21.11b1"
+description = "The uncompromising code formatter."
+category = "dev"
+optional = false
+python-versions = ">=3.6.2"
+
+[package.dependencies]
+click = ">=7.1.2"
+mypy-extensions = ">=0.4.3"
+pathspec = ">=0.9.0,<1"
+platformdirs = ">=2"
+regex = ">=2021.4.4"
+tomli = ">=0.2.6,<2.0.0"
+typed-ast = {version = ">=1.4.2", markers = "python_version < \"3.8\" and implementation_name == \"cpython\""}
+typing-extensions = [
+ {version = ">=3.10.0.0", markers = "python_version < \"3.10\""},
+ {version = "!=3.10.0.1", markers = "python_version >= \"3.10\""},
+]
+
+[package.extras]
+colorama = ["colorama (>=0.4.3)"]
+d = ["aiohttp (>=3.7.4)"]
+jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"]
+python2 = ["typed-ast (>=1.4.3)"]
+uvloop = ["uvloop (>=0.15.2)"]
+
[[package]]
name = "blinker"
version = "1.4"
@@ -297,7 +325,7 @@ python-versions = ">=3.5"
[[package]]
name = "httpcore"
-version = "0.14.2"
+version = "0.14.3"
description = "A minimal low-level HTTP client."
category = "main"
optional = false
@@ -406,6 +434,20 @@ docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
perf = ["ipython"]
testing = ["pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-flake8", "pytest-cov", "pytest-enabler (>=1.0.1)", "packaging", "pep517", "pyfakefs", "flufl.flake8", "pytest-perf (>=0.9.2)", "pytest-black (>=0.3.7)", "pytest-mypy", "importlib-resources (>=1.3)"]
+[[package]]
+name = "isort"
+version = "5.10.1"
+description = "A Python utility / library to sort Python imports."
+category = "dev"
+optional = false
+python-versions = ">=3.6.1,<4.0"
+
+[package.extras]
+pipfile_deprecated_finder = ["pipreqs", "requirementslib"]
+requirements_deprecated_finder = ["pipreqs", "pip-api"]
+colors = ["colorama (>=0.4.3,<0.5.0)"]
+plugins = ["setuptools"]
+
[[package]]
name = "itsdangerous"
version = "2.0.1"
@@ -459,6 +501,14 @@ category = "main"
optional = true
python-versions = ">=3.6"
+[[package]]
+name = "mypy-extensions"
+version = "0.4.3"
+description = "Experimental type system extensions for programs checked with the mypy typechecker."
+category = "dev"
+optional = false
+python-versions = "*"
+
[[package]]
name = "nonebot-adapter-cqhttp"
version = "2.0.0-alpha.16"
@@ -544,14 +594,34 @@ python-socketio = ">=4.6.1,<5.0.0"
[[package]]
name = "packaging"
-version = "21.2"
+version = "21.3"
description = "Core utilities for Python packages"
category = "dev"
optional = false
python-versions = ">=3.6"
[package.dependencies]
-pyparsing = ">=2.0.2,<3"
+pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
+
+[[package]]
+name = "pathspec"
+version = "0.9.0"
+description = "Utility library for gitignore style pattern matching of file paths."
+category = "dev"
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+
+[[package]]
+name = "platformdirs"
+version = "2.4.0"
+description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
+[package.extras]
+docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
+test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
[[package]]
name = "priority"
@@ -636,11 +706,14 @@ python-versions = "*"
[[package]]
name = "pyparsing"
-version = "2.4.7"
+version = "3.0.6"
description = "Python parsing module"
category = "dev"
optional = false
-python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+python-versions = ">=3.6"
+
+[package.extras]
+diagrams = ["jinja2", "railroad-diagrams"]
[[package]]
name = "python-dotenv"
@@ -722,6 +795,14 @@ werkzeug = ">=2.0.0"
[package.extras]
dotenv = ["python-dotenv"]
+[[package]]
+name = "regex"
+version = "2021.11.10"
+description = "Alternative regular expression module, to replace re."
+category = "dev"
+optional = false
+python-versions = "*"
+
[[package]]
name = "requests"
version = "2.26.0"
@@ -925,6 +1006,14 @@ category = "main"
optional = true
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+[[package]]
+name = "tomli"
+version = "1.2.2"
+description = "A lil' TOML parser"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
[[package]]
name = "tomlkit"
version = "0.7.2"
@@ -933,6 +1022,14 @@ category = "main"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
+[[package]]
+name = "typed-ast"
+version = "1.5.0"
+description = "a fork of Python 2 and 3 ast modules with type comment support"
+category = "dev"
+optional = false
+python-versions = ">=3.6"
+
[[package]]
name = "typing-extensions"
version = "4.0.0"
@@ -1100,7 +1197,7 @@ quart = ["Quart"]
[metadata]
lock-version = "1.1"
python-versions = "^3.7.3"
-content-hash = "537c91f98fd6598dbce8c2942530f18dee0858a896b6f393a684252a77dc76c6"
+content-hash = "9a64b2ba25ea3367e1636545241122d5b4d454ab3042865416193f84bf358fc3"
[metadata.files]
aiocache = [
@@ -1221,6 +1318,10 @@ babel = [
{file = "Babel-2.9.1-py2.py3-none-any.whl", hash = "sha256:ab49e12b91d937cd11f0b67cb259a57ab4ad2b59ac7a3b41d6c06c0ac5b0def9"},
{file = "Babel-2.9.1.tar.gz", hash = "sha256:bc0c176f9f6a994582230df350aa6e05ba2ebe4b3ac317eab29d9be5d2768da0"},
]
+black = [
+ {file = "black-21.11b1-py3-none-any.whl", hash = "sha256:802c6c30b637b28645b7fde282ed2569c0cd777dbe493a41b6a03c1d903f99ac"},
+ {file = "black-21.11b1.tar.gz", hash = "sha256:a042adbb18b3262faad5aff4e834ff186bb893f95ba3a8013f09de1e5569def2"},
+]
blinker = [
{file = "blinker-1.4.tar.gz", hash = "sha256:471aee25f3992bd325afa3772f1063dbdbbca947a041b8b89466dc00d606f8b6"},
]
@@ -1471,8 +1572,8 @@ html2text = [
{file = "html2text-2020.1.16.tar.gz", hash = "sha256:e296318e16b059ddb97f7a8a1d6a5c1d7af4544049a01e261731d2d5cc277bbb"},
]
httpcore = [
- {file = "httpcore-0.14.2-py3-none-any.whl", hash = "sha256:47d7c8f755719d4a57be0b6e022897e9e963bf9ce4b15b9cc006a38a1cfa2932"},
- {file = "httpcore-0.14.2.tar.gz", hash = "sha256:ff8f8b9434ec4823f95a30596fbe78039913e706d3e598b0b8955b1e1828e093"},
+ {file = "httpcore-0.14.3-py3-none-any.whl", hash = "sha256:9a98d2416b78976fc5396ff1f6b26ae9885efbb3105d24eed490f20ab4c95ec1"},
+ {file = "httpcore-0.14.3.tar.gz", hash = "sha256:d10162a63265a0228d5807964bd964478cbdb5178f9a2eedfebb2faba27eef5d"},
]
httptools = [
{file = "httptools-0.2.0-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:79dbc21f3612a78b28384e989b21872e2e3cf3968532601544696e4ed0007ce5"},
@@ -1515,6 +1616,10 @@ importlib-metadata = [
{file = "importlib_metadata-4.8.2-py3-none-any.whl", hash = "sha256:53ccfd5c134223e497627b9815d5030edf77d2ed573922f7a0b8f8bb81a1c100"},
{file = "importlib_metadata-4.8.2.tar.gz", hash = "sha256:75bdec14c397f528724c1bfd9709d660b33a4d2e77387a3358f20b848bb5e5fb"},
]
+isort = [
+ {file = "isort-5.10.1-py3-none-any.whl", hash = "sha256:6f62d78e2f89b4500b080fe3a81690850cd254227f27f75c3a0c491a1f351ba7"},
+ {file = "isort-5.10.1.tar.gz", hash = "sha256:e8443a5e7a020e9d7f97f1d7d9cd17c88bcb3bc7e218bf9cf5095fe550be2951"},
+]
itsdangerous = [
{file = "itsdangerous-2.0.1-py3-none-any.whl", hash = "sha256:5174094b9637652bdb841a3029700391451bd092ba3db90600dea710ba28e97c"},
{file = "itsdangerous-2.0.1.tar.gz", hash = "sha256:9e724d68fc22902a1435351f84c3fb8623f303fffcc566a4cb952df8c572cff0"},
@@ -1672,6 +1777,10 @@ multidict = [
{file = "multidict-5.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:c9631c642e08b9fff1c6255487e62971d8b8e821808ddd013d8ac058087591ac"},
{file = "multidict-5.2.0.tar.gz", hash = "sha256:0dd1c93edb444b33ba2274b66f63def8a327d607c6c790772f448a53b6ea59ce"},
]
+mypy-extensions = [
+ {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
+ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
+]
nonebot-adapter-cqhttp = []
nonebot-adapter-ding = []
nonebot-adapter-feishu = []
@@ -1681,8 +1790,16 @@ nonebot-plugin-test = [
{file = "nonebot_plugin_test-0.3.0-py3-none-any.whl", hash = "sha256:edb880340436323ccd0a13b31d48975136b6bdc71daa178601c4b05b068cc73e"},
]
packaging = [
- {file = "packaging-21.2-py3-none-any.whl", hash = "sha256:14317396d1e8cdb122989b916fa2c7e9ca8e2be9e8060a6eff75b6b7b4d8a7e0"},
- {file = "packaging-21.2.tar.gz", hash = "sha256:096d689d78ca690e4cd8a89568ba06d07ca097e3306a4381635073ca91479966"},
+ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
+ {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
+]
+pathspec = [
+ {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"},
+ {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"},
+]
+platformdirs = [
+ {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"},
+ {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"},
]
priority = [
{file = "priority-2.0.0-py3-none-any.whl", hash = "sha256:6f8eefce5f3ad59baf2c080a664037bb4725cd0a790d53d59ab4059288faf6aa"},
@@ -1793,8 +1910,8 @@ pygtrie = [
{file = "pygtrie-2.4.2.tar.gz", hash = "sha256:43205559d28863358dbbf25045029f58e2ab357317a59b11f11ade278ac64692"},
]
pyparsing = [
- {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"},
- {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"},
+ {file = "pyparsing-3.0.6-py3-none-any.whl", hash = "sha256:04ff808a5b90911829c55c4e26f75fa5ca8a2f5f36aa3a51f68e27033341d3e4"},
+ {file = "pyparsing-3.0.6.tar.gz", hash = "sha256:d9bdec0013ef1eb5a84ab39a3b3868911598afa494f5faa038647101504e2b81"},
]
python-dotenv = [
{file = "python-dotenv-0.19.2.tar.gz", hash = "sha256:a5de49a31e953b45ff2d2fd434bbc2670e8db5273606c1e737cc6b93eff3655f"},
@@ -1851,6 +1968,57 @@ quart = [
{file = "Quart-0.15.1-py3-none-any.whl", hash = "sha256:f35134fb1d81af61624e6d89bca33cd611dcedce2dc4e291f527ab04395f4e1a"},
{file = "Quart-0.15.1.tar.gz", hash = "sha256:f80c91d1e0588662483e22dd9c368a5778886b62e128c5399d2cc1b1898482cf"},
]
+regex = [
+ {file = "regex-2021.11.10-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9345b6f7ee578bad8e475129ed40123d265464c4cfead6c261fd60fc9de00bcf"},
+ {file = "regex-2021.11.10-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:416c5f1a188c91e3eb41e9c8787288e707f7d2ebe66e0a6563af280d9b68478f"},
+ {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0538c43565ee6e703d3a7c3bdfe4037a5209250e8502c98f20fea6f5fdf2965"},
+ {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee1227cf08b6716c85504aebc49ac827eb88fcc6e51564f010f11a406c0a667"},
+ {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6650f16365f1924d6014d2ea770bde8555b4a39dc9576abb95e3cd1ff0263b36"},
+ {file = "regex-2021.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ab804ea73972049b7a2a5c62d97687d69b5a60a67adca07eb73a0ddbc9e29f"},
+ {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:68a067c11463de2a37157930d8b153005085e42bcb7ad9ca562d77ba7d1404e0"},
+ {file = "regex-2021.11.10-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:162abfd74e88001d20cb73ceaffbfe601469923e875caf9118333b1a4aaafdc4"},
+ {file = "regex-2021.11.10-cp310-cp310-win32.whl", hash = "sha256:98ba568e8ae26beb726aeea2273053c717641933836568c2a0278a84987b2a1a"},
+ {file = "regex-2021.11.10-cp310-cp310-win_amd64.whl", hash = "sha256:780b48456a0f0ba4d390e8b5f7c661fdd218934388cde1a974010a965e200e12"},
+ {file = "regex-2021.11.10-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:dba70f30fd81f8ce6d32ddeef37d91c8948e5d5a4c63242d16a2b2df8143aafc"},
+ {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e1f54b9b4b6c53369f40028d2dd07a8c374583417ee6ec0ea304e710a20f80a0"},
+ {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fbb9dc00e39f3e6c0ef48edee202f9520dafb233e8b51b06b8428cfcb92abd30"},
+ {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666abff54e474d28ff42756d94544cdfd42e2ee97065857413b72e8a2d6a6345"},
+ {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5537f71b6d646f7f5f340562ec4c77b6e1c915f8baae822ea0b7e46c1f09b733"},
+ {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2e07c6a26ed4bea91b897ee2b0835c21716d9a469a96c3e878dc5f8c55bb23"},
+ {file = "regex-2021.11.10-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ca5f18a75e1256ce07494e245cdb146f5a9267d3c702ebf9b65c7f8bd843431e"},
+ {file = "regex-2021.11.10-cp36-cp36m-win32.whl", hash = "sha256:93a5051fcf5fad72de73b96f07d30bc29665697fb8ecdfbc474f3452c78adcf4"},
+ {file = "regex-2021.11.10-cp36-cp36m-win_amd64.whl", hash = "sha256:b483c9d00a565633c87abd0aaf27eb5016de23fed952e054ecc19ce32f6a9e7e"},
+ {file = "regex-2021.11.10-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:fff55f3ce50a3ff63ec8e2a8d3dd924f1941b250b0aac3d3d42b687eeff07a8e"},
+ {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e32d2a2b02ccbef10145df9135751abea1f9f076e67a4e261b05f24b94219e36"},
+ {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:53db2c6be8a2710b359bfd3d3aa17ba38f8aa72a82309a12ae99d3c0c3dcd74d"},
+ {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2207ae4f64ad3af399e2d30dde66f0b36ae5c3129b52885f1bffc2f05ec505c8"},
+ {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5ca078bb666c4a9d1287a379fe617a6dccd18c3e8a7e6c7e1eb8974330c626a"},
+ {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:dd33eb9bdcfbabab3459c9ee651d94c842bc8a05fabc95edf4ee0c15a072495e"},
+ {file = "regex-2021.11.10-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:05b7d6d7e64efe309972adab77fc2af8907bb93217ec60aa9fe12a0dad35874f"},
+ {file = "regex-2021.11.10-cp37-cp37m-win32.whl", hash = "sha256:e71255ba42567d34a13c03968736c5d39bb4a97ce98188fafb27ce981115beec"},
+ {file = "regex-2021.11.10-cp37-cp37m-win_amd64.whl", hash = "sha256:07856afef5ffcc052e7eccf3213317fbb94e4a5cd8177a2caa69c980657b3cb4"},
+ {file = "regex-2021.11.10-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba05430e819e58544e840a68b03b28b6d328aff2e41579037e8bab7653b37d83"},
+ {file = "regex-2021.11.10-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7f301b11b9d214f83ddaf689181051e7f48905568b0c7017c04c06dfd065e244"},
+ {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aaa4e0705ef2b73dd8e36eeb4c868f80f8393f5f4d855e94025ce7ad8525f50"},
+ {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:788aef3549f1924d5c38263104dae7395bf020a42776d5ec5ea2b0d3d85d6646"},
+ {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f8af619e3be812a2059b212064ea7a640aff0568d972cd1b9e920837469eb3cb"},
+ {file = "regex-2021.11.10-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85bfa6a5413be0ee6c5c4a663668a2cad2cbecdee367630d097d7823041bdeec"},
+ {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f23222527b307970e383433daec128d769ff778d9b29343fb3496472dc20dabe"},
+ {file = "regex-2021.11.10-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:da1a90c1ddb7531b1d5ff1e171b4ee61f6345119be7351104b67ff413843fe94"},
+ {file = "regex-2021.11.10-cp38-cp38-win32.whl", hash = "sha256:0617383e2fe465732af4509e61648b77cbe3aee68b6ac8c0b6fe934db90be5cc"},
+ {file = "regex-2021.11.10-cp38-cp38-win_amd64.whl", hash = "sha256:a3feefd5e95871872673b08636f96b61ebef62971eab044f5124fb4dea39919d"},
+ {file = "regex-2021.11.10-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f7f325be2804246a75a4f45c72d4ce80d2443ab815063cdf70ee8fb2ca59ee1b"},
+ {file = "regex-2021.11.10-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:537ca6a3586931b16a85ac38c08cc48f10fc870a5b25e51794c74df843e9966d"},
+ {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eef2afb0fd1747f33f1ee3e209bce1ed582d1896b240ccc5e2697e3275f037c7"},
+ {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:432bd15d40ed835a51617521d60d0125867f7b88acf653e4ed994a1f8e4995dc"},
+ {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b43c2b8a330a490daaef5a47ab114935002b13b3f9dc5da56d5322ff218eeadb"},
+ {file = "regex-2021.11.10-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:962b9a917dd7ceacbe5cd424556914cb0d636001e393b43dc886ba31d2a1e449"},
+ {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fa8c626d6441e2d04b6ee703ef2d1e17608ad44c7cb75258c09dd42bacdfc64b"},
+ {file = "regex-2021.11.10-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:3c5fb32cc6077abad3bbf0323067636d93307c9fa93e072771cf9a64d1c0f3ef"},
+ {file = "regex-2021.11.10-cp39-cp39-win32.whl", hash = "sha256:3b5df18db1fccd66de15aa59c41e4f853b5df7550723d26aa6cb7f40e5d9da5a"},
+ {file = "regex-2021.11.10-cp39-cp39-win_amd64.whl", hash = "sha256:83ee89483672b11f8952b158640d0c0ff02dc43d9cb1b70c1564b49abe92ce29"},
+ {file = "regex-2021.11.10.tar.gz", hash = "sha256:f341ee2df0999bfdf7a95e448075effe0db212a59387de1a70690e4acb03d4c6"},
+]
requests = [
{file = "requests-2.26.0-py2.py3-none-any.whl", hash = "sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24"},
{file = "requests-2.26.0.tar.gz", hash = "sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7"},
@@ -1908,10 +2076,35 @@ toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
+tomli = [
+ {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"},
+ {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"},
+]
tomlkit = [
{file = "tomlkit-0.7.2-py2.py3-none-any.whl", hash = "sha256:173ad840fa5d2aac140528ca1933c29791b79a374a0861a80347f42ec9328117"},
{file = "tomlkit-0.7.2.tar.gz", hash = "sha256:d7a454f319a7e9bd2e249f239168729327e4dd2d27b17dc68be264ad1ce36754"},
]
+typed-ast = [
+ {file = "typed_ast-1.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b310a207ee9fde3f46ba327989e6cba4195bc0c8c70a158456e7b10233e6bed"},
+ {file = "typed_ast-1.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:52ca2b2b524d770bed7a393371a38e91943f9160a190141e0df911586066ecda"},
+ {file = "typed_ast-1.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:14fed8820114a389a2b7e91624db5f85f3f6682fda09fe0268a59aabd28fe5f5"},
+ {file = "typed_ast-1.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:65c81abbabda7d760df7304d843cc9dbe7ef5d485504ca59a46ae2d1731d2428"},
+ {file = "typed_ast-1.5.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:37ba2ab65a0028b1a4f2b61a8fe77f12d242731977d274a03d68ebb751271508"},
+ {file = "typed_ast-1.5.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:49af5b8f6f03ed1eb89ee06c1d7c2e7c8e743d720c3746a5857609a1abc94c94"},
+ {file = "typed_ast-1.5.0-cp36-cp36m-win_amd64.whl", hash = "sha256:e4374a76e61399a173137e7984a1d7e356038cf844f24fd8aea46c8029a2f712"},
+ {file = "typed_ast-1.5.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:ea517c2bb11c5e4ba7a83a91482a2837041181d57d3ed0749a6c382a2b6b7086"},
+ {file = "typed_ast-1.5.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:51040bf45aacefa44fa67fb9ebcd1f2bec73182b99a532c2394eea7dabd18e24"},
+ {file = "typed_ast-1.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:806e0c7346b9b4af8c62d9a29053f484599921a4448c37fbbcbbf15c25138570"},
+ {file = "typed_ast-1.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a67fd5914603e2165e075f1b12f5a8356bfb9557e8bfb74511108cfbab0f51ed"},
+ {file = "typed_ast-1.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:224afecb8b39739f5c9562794a7c98325cb9d972712e1a98b6989a4720219541"},
+ {file = "typed_ast-1.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:155b74b078be842d2eb630dd30a280025eca0a5383c7d45853c27afee65f278f"},
+ {file = "typed_ast-1.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:361b9e5d27bd8e3ccb6ea6ad6c4f3c0be322a1a0f8177db6d56264fa0ae40410"},
+ {file = "typed_ast-1.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:618912cbc7e17b4aeba86ffe071698c6e2d292acbd6d1d5ec1ee724b8c4ae450"},
+ {file = "typed_ast-1.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7e6731044f748340ef68dcadb5172a4b1f40847a2983fe3983b2a66445fbc8e6"},
+ {file = "typed_ast-1.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:e8a9b9c87801cecaad3b4c2b8876387115d1a14caa602c1618cedbb0cb2a14e6"},
+ {file = "typed_ast-1.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:ec184dfb5d3d11e82841dbb973e7092b75f306b625fad7b2e665b64c5d60ab3f"},
+ {file = "typed_ast-1.5.0.tar.gz", hash = "sha256:ff4ad88271aa7a55f19b6a161ed44e088c393846d954729549e3cde8257747bb"},
+]
typing-extensions = [
{file = "typing_extensions-4.0.0-py3-none-any.whl", hash = "sha256:829704698b22e13ec9eaf959122315eabb370b0884400e9818334d8b677023d9"},
{file = "typing_extensions-4.0.0.tar.gz", hash = "sha256:2cdf80e4e04866a9b3689a51869016d36db0814d84b8d8a568d22781d45d27ed"},
diff --git a/pyproject.toml b/pyproject.toml
index 404eb0ac..1b00e887 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -36,8 +36,9 @@ uvicorn = { version = "^0.15.0", extras = ["standard"] }
aiohttp = { version = "^3.7.4", extras = ["speedups"], optional = true }
[tool.poetry.dev-dependencies]
-yapf = "^0.31.0"
sphinx = "^4.1.1"
+isort = "^5.10.1"
+black = "^21.11b1"
nonebot-plugin-test = "^0.3.0"
nonebot-adapter-cqhttp = { path = "./packages/nonebot-adapter-cqhttp", develop = true }
nonebot-adapter-ding = { path = "./packages/nonebot-adapter-ding", develop = true }
@@ -55,13 +56,21 @@ all = ["quart", "aiohttp"]
# url = "https://mirrors.aliyun.com/pypi/simple/"
# default = true
+[tool.black]
+line-length = 88
+target-version = ["py37", "py38", "py39", "py310"]
+include = '\.pyi?$'
+extend-exclude = '''
+'''
+
[tool.isort]
+profile = "black"
line_length = 80
length_sort = true
skip_gitignore = true
force_sort_within_sections = true
-known_local_folder = "nonebot"
-extra_standard_library = "typing_extensions"
+known_local_folder = ["nonebot"]
+extra_standard_library = ["typing_extensions"]
[build-system]
requires = ["poetry_core>=1.0.0"]
diff --git a/tests/bot.py b/tests/bot.py
index ef719db0..739078b2 100644
--- a/tests/bot.py
+++ b/tests/bot.py
@@ -11,11 +11,9 @@ from nonebot.adapters.mirai import Bot as MiraiBot
from nonebot.adapters.feishu import Bot as FeishuBot
# test custom log
-logger.add("error.log",
- rotation="00:00",
- diagnose=False,
- level="ERROR",
- format=default_format)
+logger.add(
+ "error.log", rotation="00:00", diagnose=False, level="ERROR", format=default_format
+)
nonebot.init(custom_config2="config on init")
app = nonebot.get_asgi()
diff --git a/tests/test_plugins/test_ding.py b/tests/test_plugins/test_ding.py
index ad9b8d4c..234d07fe 100644
--- a/tests/test_plugins/test_ding.py
+++ b/tests/test_plugins/test_ding.py
@@ -1,7 +1,8 @@
-from nonebot.adapters.ding.event import GroupMessageEvent, PrivateMessageEvent
from nonebot.rule import to_me
from nonebot.plugin import on_command
-from nonebot.adapters.ding import Bot as DingBot, MessageSegment, MessageEvent
+from nonebot.adapters.ding import Bot as DingBot
+from nonebot.adapters.ding import MessageEvent, MessageSegment
+from nonebot.adapters.ding.event import GroupMessageEvent, PrivateMessageEvent
helper = on_command("ding_helper", to_me())
@@ -34,7 +35,7 @@ markdown = on_command("markdown", to_me())
async def markdown_handler(bot: DingBot):
message = MessageSegment.markdown(
"Hello, This is NoneBot",
- "#### NoneBot \n> Nonebot 是一款高性能的 Python 机器人框架\n> ![screenshot](https://v2.nonebot.dev/logo.png)\n> [GitHub 仓库地址](https://github.com/nonebot/nonebot2) \n"
+ "#### NoneBot \n> Nonebot 是一款高性能的 Python 机器人框架\n> ![screenshot](https://v2.nonebot.dev/logo.png)\n> [GitHub 仓库地址](https://github.com/nonebot/nonebot2) \n",
)
await markdown.finish(message)
@@ -46,10 +47,10 @@ actionCardSingleBtn = on_command("actionCardSingleBtn", to_me())
async def actionCardSingleBtn_handler(bot: DingBot):
message = MessageSegment.actionCardSingleBtn(
title="打造一间咖啡厅",
- text=
- "![screenshot](https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png) \n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
+ text="![screenshot](https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png) \n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
singleTitle="阅读全文",
- singleURL="https://www.dingtalk.com/")
+ singleURL="https://www.dingtalk.com/",
+ )
await actionCardSingleBtn.finish(message)
@@ -58,26 +59,21 @@ actionCard = on_command("actionCard", to_me())
@actionCard.handle()
async def actionCard_handler(bot: DingBot):
- message = MessageSegment.raw({
- "msgtype": "actionCard",
- "actionCard": {
- "title":
- "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
- "text":
- "![screenshot](https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png) \n\n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
- "hideAvatar":
- "0",
- "btnOrientation":
- "0",
- "btns": [{
- "title": "内容不错",
- "actionURL": "https://www.dingtalk.com/"
- }, {
- "title": "不感兴趣",
- "actionURL": "https://www.dingtalk.com/"
- }]
+ message = MessageSegment.raw(
+ {
+ "msgtype": "actionCard",
+ "actionCard": {
+ "title": "乔布斯 20 年前想打造一间苹果咖啡厅,而它正是 Apple Store 的前身",
+ "text": "![screenshot](https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png) \n\n #### 乔布斯 20 年前想打造的苹果咖啡厅 \n\n Apple Store 的设计正从原来满满的科技感走向生活化,而其生活化的走向其实可以追溯到 20 年前苹果一个建立咖啡馆的计划",
+ "hideAvatar": "0",
+ "btnOrientation": "0",
+ "btns": [
+ {"title": "内容不错", "actionURL": "https://www.dingtalk.com/"},
+ {"title": "不感兴趣", "actionURL": "https://www.dingtalk.com/"},
+ ],
+ },
}
- })
+ )
await actionCard.finish(message, at_sender=True)
@@ -86,26 +82,25 @@ feedCard = on_command("feedCard", to_me())
@feedCard.handle()
async def feedCard_handler(bot: DingBot):
- message = MessageSegment.raw({
- "msgtype": "feedCard",
- "feedCard": {
- "links": [{
- "title":
- "时代的火车向前开1",
- "messageURL":
- "https://www.dingtalk.com/",
- "picURL":
- "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
- }, {
- "title":
- "时代的火车向前开2",
- "messageURL":
- "https://www.dingtalk.com/",
- "picURL":
- "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png"
- }]
+ message = MessageSegment.raw(
+ {
+ "msgtype": "feedCard",
+ "feedCard": {
+ "links": [
+ {
+ "title": "时代的火车向前开1",
+ "messageURL": "https://www.dingtalk.com/",
+ "picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png",
+ },
+ {
+ "title": "时代的火车向前开2",
+ "messageURL": "https://www.dingtalk.com/",
+ "picURL": "https://img.alicdn.com/tfs/TB1NwmBEL9TBuNjy1zbXXXpepXa-2400-1218.png",
+ },
+ ]
+ },
}
- })
+ )
await feedCard.finish(message)
@@ -115,7 +110,8 @@ atme = on_command("atme", to_me())
@atme.handle()
async def atme_handler(bot: DingBot, event: MessageEvent):
message = f"@{event.senderId} manually at you" + MessageSegment.atDingtalkIds(
- event.senderId)
+ event.senderId
+ )
await atme.send("matcher send auto at you", at_sender=True)
await bot.send(event, "bot send auto at you", at_sender=True)
await atme.finish(message)
@@ -143,12 +139,12 @@ async def textAdd_handler(bot: DingBot, event: MessageEvent):
message = message + MessageSegment.text("第二段消息\n")
await textAdd.send(message)
- message = message + MessageSegment.text(
- "\n第三段消息\n") + "adfkasfkhsdkfahskdjasdashdkjasdf"
- message = message + MessageSegment.extension({
- "text_type": "code_snippet",
- "code_language": "C#"
- })
+ message = (
+ message + MessageSegment.text("\n第三段消息\n") + "adfkasfkhsdkfahskdjasdashdkjasdf"
+ )
+ message = message + MessageSegment.extension(
+ {"text_type": "code_snippet", "code_language": "C#"}
+ )
await textAdd.send(message)
@@ -159,7 +155,8 @@ code = on_command("code", to_me())
async def code_handler(bot: DingBot, event: MessageEvent):
raw = MessageSegment.code("Python", 'print("hello world")')
await code.send(raw)
- message = MessageSegment.text("""using System;
+ message = MessageSegment.text(
+ """using System;
namespace HelloWorld
{
@@ -170,11 +167,11 @@ namespace HelloWorld
Console.WriteLine("Hello World!");
}
}
-}""")
- message += MessageSegment.extension({
- "text_type": "code_snippet",
- "code_language": "C#"
- })
+}"""
+ )
+ message += MessageSegment.extension(
+ {"text_type": "code_snippet", "code_language": "C#"}
+ )
await code.finish(message)
@@ -196,12 +193,12 @@ hello = on_command("hello", to_me())
@hello.handle()
async def hello_handler(bot: DingBot, event: MessageEvent):
- message = MessageSegment.raw({
- "msgtype": "text",
- "text": {
- "content": 'hello '
- },
- })
+ message = MessageSegment.raw(
+ {
+ "msgtype": "text",
+ "text": {"content": "hello "},
+ }
+ )
message += MessageSegment.atDingtalkIds(event.senderId)
await hello.send(message)
@@ -216,22 +213,21 @@ hello = on_command("webhook", to_me())
@hello.handle()
async def webhook_handler(bot: DingBot, event: MessageEvent):
print(event)
- message = MessageSegment.raw({
- "msgtype": "text",
- "text": {
- "content": 'hello from webhook,一定要注意安全方式的鉴权哦,否则可能发送失败的'
- },
- })
+ message = MessageSegment.raw(
+ {
+ "msgtype": "text",
+ "text": {"content": "hello from webhook,一定要注意安全方式的鉴权哦,否则可能发送失败的"},
+ }
+ )
message += MessageSegment.atDingtalkIds(event.senderId)
await hello.send(
message,
- webhook=
- "https://oapi.dingtalk.com/robot/send?access_token=XXXXXXXXXXXXXX",
- secret="SECXXXXXXXXXXXXXXXXXXXXXXXXX")
+ webhook="https://oapi.dingtalk.com/robot/send?access_token=XXXXXXXXXXXXXX",
+ secret="SECXXXXXXXXXXXXXXXXXXXXXXXXX",
+ )
message = MessageSegment.text("TEST 123123 S")
await hello.send(
message,
- webhook=
- "https://oapi.dingtalk.com/robot/send?access_token=XXXXXXXXXXXXXX",
+ webhook="https://oapi.dingtalk.com/robot/send?access_token=XXXXXXXXXXXXXX",
)
diff --git a/tests/test_plugins/test_feishu.py b/tests/test_plugins/test_feishu.py
index 960ae377..5d8726eb 100644
--- a/tests/test_plugins/test_feishu.py
+++ b/tests/test_plugins/test_feishu.py
@@ -1,6 +1,7 @@
-from nonebot.plugin import on_command
from nonebot.typing import T_State
-from nonebot.adapters.feishu import Bot as FeishuBot, MessageEvent
+from nonebot.plugin import on_command
+from nonebot.adapters.feishu import MessageEvent
+from nonebot.adapters.feishu import Bot as FeishuBot
helper = on_command("say")
diff --git a/tests/test_plugins/test_get_export.py b/tests/test_plugins/test_get_export.py
index ec4437d1..1bf06602 100644
--- a/tests/test_plugins/test_get_export.py
+++ b/tests/test_plugins/test_get_export.py
@@ -1,5 +1,4 @@
import nonebot
-
from .test_export import export
print(export, nonebot.require("test_export"))
diff --git a/tests/test_plugins/test_group/__init__.py b/tests/test_plugins/test_group/__init__.py
index 9d1d04a7..cd081381 100644
--- a/tests/test_plugins/test_group/__init__.py
+++ b/tests/test_plugins/test_group/__init__.py
@@ -4,4 +4,4 @@ from nonebot import CommandGroup, MatcherGroup
cmd = CommandGroup("test", rule=to_me())
match = MatcherGroup(priority=2)
-from . import commands, matches
+from . import matches, commands
diff --git a/tests/test_plugins/test_group/commands.py b/tests/test_plugins/test_group/commands.py
index 4d0898b9..71968351 100644
--- a/tests/test_plugins/test_group/commands.py
+++ b/tests/test_plugins/test_group/commands.py
@@ -1,6 +1,5 @@
-from nonebot.adapters import Bot, Event
-
from . import cmd
+from nonebot.adapters import Bot, Event
test_1 = cmd.command("1", aliases={"test"})
diff --git a/tests/test_plugins/test_group/matches.py b/tests/test_plugins/test_group/matches.py
index d33d8dc7..595fd6a4 100644
--- a/tests/test_plugins/test_group/matches.py
+++ b/tests/test_plugins/test_group/matches.py
@@ -1,9 +1,8 @@
+from . import match
from nonebot.typing import T_State
from nonebot.adapters import Bot, Event
from nonebot.adapters.cqhttp import HeartbeatMetaEvent
-from . import match
-
async def heartbeat(bot: Bot, event: Event, state: T_State) -> bool:
return isinstance(event, HeartbeatMetaEvent)
diff --git a/tests/test_plugins/test_metaevent.py b/tests/test_plugins/test_metaevent.py
index e2a160e2..98f76f78 100644
--- a/tests/test_plugins/test_metaevent.py
+++ b/tests/test_plugins/test_metaevent.py
@@ -1,6 +1,6 @@
from nonebot.typing import T_State
-from nonebot.plugin import on_metaevent
from nonebot.adapters import Bot, Event
+from nonebot.plugin import on_metaevent
from nonebot.adapters.cqhttp import HeartbeatMetaEvent
diff --git a/tests/test_plugins/test_mirai.py b/tests/test_plugins/test_mirai.py
index c518290a..08b23e34 100644
--- a/tests/test_plugins/test_mirai.py
+++ b/tests/test_plugins/test_mirai.py
@@ -1,8 +1,8 @@
-from nonebot.plugin import on_keyword, on_command
from nonebot.rule import to_me
+from nonebot.plugin import on_command, on_keyword
from nonebot.adapters.mirai import Bot, MessageEvent
-message_test = on_keyword({'reply'}, rule=to_me())
+message_test = on_keyword({"reply"}, rule=to_me())
@message_test.handle()
@@ -11,10 +11,10 @@ async def _message(bot: Bot, event: MessageEvent):
await bot.send(event, text, at_sender=True)
-command_test = on_command('miecho')
+command_test = on_command("miecho")
@command_test.handle()
async def _echo(bot: Bot, event: MessageEvent):
text = event.get_plaintext()
- await bot.send(event, text, at_sender=True)
\ No newline at end of file
+ await bot.send(event, text, at_sender=True)
diff --git a/tests/test_plugins/test_overload.py b/tests/test_plugins/test_overload.py
index 06712779..4e9074e5 100644
--- a/tests/test_plugins/test_overload.py
+++ b/tests/test_plugins/test_overload.py
@@ -1,5 +1,5 @@
from nonebot import on_command
-from nonebot.adapters.cqhttp import Bot, PrivateMessageEvent, GroupMessageEvent
+from nonebot.adapters.cqhttp import Bot, GroupMessageEvent, PrivateMessageEvent
overload = on_command("overload")
diff --git a/tests/test_plugins/test_permission.py b/tests/test_plugins/test_permission.py
index 1f8b71d6..51e2f7cd 100644
--- a/tests/test_plugins/test_permission.py
+++ b/tests/test_plugins/test_permission.py
@@ -1,7 +1,7 @@
from nonebot.rule import to_me
from nonebot.typing import T_State
-from nonebot.plugin import on_startswith
from nonebot.permission import SUPERUSER
+from nonebot.plugin import on_startswith
from nonebot.adapters.ding import Bot as DingBot
from nonebot.adapters.cqhttp import Bot as CQHTTPBot
diff --git a/tests/test_plugins/test_shell.py b/tests/test_plugins/test_shell.py
index 63719b42..3428406c 100644
--- a/tests/test_plugins/test_shell.py
+++ b/tests/test_plugins/test_shell.py
@@ -1,7 +1,7 @@
from nonebot.adapters import Bot
from nonebot.typing import T_State
from nonebot import on_shell_command
-from nonebot.rule import to_me, ArgumentParser
+from nonebot.rule import ArgumentParser, to_me
parser = ArgumentParser()
parser.add_argument("-a", action="store_true")