Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 13 additions & 30 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@

# Created by https://www.toptal.com/developers/gitignore/api/visualstudiocode,python
# Edit at https://www.toptal.com/developers/gitignore?templates=visualstudiocode,python

### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
Expand Down Expand Up @@ -106,7 +101,17 @@ ipython_config.py
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# PEP 582; used by e.g. github.com/David-OConnor/pyflow
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm-project.org/#use-with-ide
.pdm.toml
.pdm-python
.pdm-build/

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
Expand Down Expand Up @@ -154,27 +159,5 @@ cython_debug/
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

### VisualStudioCode ###
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
!.vscode/*.code-snippets

# Local History for Visual Studio Code
.history/

# Built Visual Studio Code Extensions
*.vsix

### VisualStudioCode Patch ###
# Ignore all local history of files
.history
.ionide

# Support for Project snippet scope

# End of https://www.toptal.com/developers/gitignore/api/visualstudiocode,python
.idea/
.env.prod
4 changes: 0 additions & 4 deletions .pdm.toml

This file was deleted.

2 changes: 1 addition & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"python.formatting.provider": "black",
"[python]": {
"editor.codeActionsOnSave": {
"source.organizeImports": true
"source.organizeImports": "explicit"
}
}
}
10 changes: 5 additions & 5 deletions example.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from typing import TYPE_CHECKING, Type, cast
from typing import TYPE_CHECKING, cast

from nonebot import on_command
from nonebot.adapters import Event, MessageSegment
from nonebot.matcher import Matcher
from nonebot.adapters import Event, MessageSegment

from nonebot_plugin_params import (
FEISHU,
Expand All @@ -26,15 +26,15 @@ async def _(
matcher: Matcher,
event: Event,
adapter_name: str = AdapterName(),
MS: Type[MessageSegment] = MessageSegmentClass(),
MS: type[MessageSegment] = MessageSegmentClass(),
) -> None:
await matcher.send("欢迎来到 wordle")
if adapter_name == ONEBOT:
MS = cast("Type[Onebot_MessageSegment]", MS) # only for type hint
MS = cast("type[Onebot_MessageSegment]", MS) # only for type hint
await matcher.send(MS.at(event.get_user_id()) + MS.text("mua~"))
# user id like "1748272409"

elif adapter_name == FEISHU:
MS = cast("Type[Feishu_MessageSegment]", MS) # only for type hint
MS = cast("type[Feishu_MessageSegment]", MS) # only for type hint
await matcher.send(MS.at(event.get_user_id()) + MS.text("mua~"))
# user id like "3e3cf96b"
25 changes: 21 additions & 4 deletions nonebot_plugin_params/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,28 @@
from nonebot.plugin import PluginMetadata

from .consts import FEISHU as FEISHU
from .consts import ONEBOT as ONEBOT
from .consts import QQGUILD as QQGUILD
from .consts import TELEGRAM as TELEGRAM
from .deps import AdapterName as AdapterName
from .deps import EventName as EventName
from .deps import ImageSegmentMethod as ImageSegmentMethod
from .deps import MessageSegmentClass as MessageSegmentClass
from .permission import PRIVATEMESSAGE as PRIVATEMESSAGE
from .deps import AdapterName as AdapterName
from .rule import allow_adapters as allow_adapters
from .permission import PRIVATEMESSAGE as PRIVATEMESSAGE
from .deps import ImageSegmentMethod as ImageSegmentMethod
from .rule import is_private_message as is_private_message
from .deps import MessageSegmentClass as MessageSegmentClass

__plugin_meta__ = PluginMetadata(
name="plugin-params",
description="提供便利的函数用于实现多适配器兼容",
usage="from nonebot_plugin_params import is_private_message",
homepage="https://github.com/iyume/nonebot-plugin-params",
type="library",
config=None,
supported_adapters={"~onebot.v11", "~qq", "~feishu", "~telegram"},
extra={
"author": "iyume",
"priority": 1,
"version": "0.1.1",
},
)
2 changes: 1 addition & 1 deletion nonebot_plugin_params/consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ class Adapter(str, Enum):
ONEBOT = "OneBot V11"
FEISHU = "Feishu"
TELEGRAM = "Telegram"
QQGUILD = "QQ Guild"
QQGUILD = "QQ"


ONEBOT = Adapter.ONEBOT
Expand Down
37 changes: 19 additions & 18 deletions nonebot_plugin_params/deps.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
from functools import lru_cache
from io import BytesIO
from pathlib import Path
from typing import TYPE_CHECKING, Awaitable, Callable, Optional, Type, Union, cast
from functools import lru_cache
from typing import TYPE_CHECKING, Union, Callable, Optional, cast
from collections.abc import Awaitable

from nonebot.adapters import Bot, Event, MessageSegment
from nonebot.params import Depends
from nonebot.adapters import Bot, Event, MessageSegment

from .consts import FEISHU, ONEBOT, QQGUILD, TELEGRAM
from .exception import NotSupportException
from .consts import FEISHU, ONEBOT, QQGUILD, TELEGRAM

if TYPE_CHECKING:
from nonebot.adapters.qq import MessageSegment as QQGuild_MessageSegment
from nonebot.adapters.feishu import MessageSegment as Feishu_MessageSegment
from nonebot.adapters.onebot.v11 import MessageSegment as OneBot_MessageSegment
from nonebot.adapters.qqguild import MessageSegment as QQGuild_MessageSegment


async def _event_name(event: Event) -> str:
Expand All @@ -32,7 +33,7 @@ def AdapterName() -> str:
return Depends(_adapter_name)


def _generic_message_segment_class(bot: Bot, _fake_key: int) -> Type[MessageSegment]:
def _generic_message_segment_class(bot: Bot, _fake_key: int) -> type[MessageSegment]:
"""This is implicit, so only use if adapter not support.

`_fake_key` prevent this function to be a dependency.
Expand All @@ -44,7 +45,7 @@ def _generic_message_segment_class(bot: Bot, _fake_key: int) -> Type[MessageSegm


@lru_cache(maxsize=10)
def __message_segment_class(adapter_name: str) -> Optional[Type[MessageSegment]]:
def __message_segment_class(adapter_name: str) -> Optional[type[MessageSegment]]:
if adapter_name == ONEBOT:
from nonebot.adapters.onebot.v11 import MessageSegment

Expand All @@ -56,21 +57,21 @@ def __message_segment_class(adapter_name: str) -> Optional[Type[MessageSegment]]
return MessageSegment

elif adapter_name == QQGUILD:
from nonebot.adapters.qqguild import MessageSegment
from nonebot.adapters.qq import MessageSegment

return MessageSegment


async def _message_segment_class(
bot: Bot, adapter_name: str = AdapterName()
) -> Type[MessageSegment]:
) -> type[MessageSegment]:
ms = __message_segment_class(adapter_name)
if ms is None:
return _generic_message_segment_class(bot, 0)
return ms


def MessageSegmentClass() -> Type[MessageSegment]:
def MessageSegmentClass() -> type[MessageSegment]:
"""获取 Adapter 对应的 MessageSegment 类。

适配: OneBot, Feishu, QQGuild
Expand All @@ -82,7 +83,7 @@ def MessageSegmentClass() -> Type[MessageSegment]:
class _get_image_segment:
bot: Bot
adapter_name: str
_MS: Type[MessageSegment]
_MS: type[MessageSegment]

auto_convertion: bool = True
"""如果能够转换,则自动转换图片类型。如 Path 转 str, BytesIO 转 bytes。"""
Expand All @@ -91,20 +92,20 @@ def __init__(
self,
bot: Bot,
adapter_name: str = AdapterName(),
MS: Type[MessageSegment] = MessageSegmentClass(),
MS: type[MessageSegment] = MessageSegmentClass(),
) -> None:
self.bot = bot
self.adapter_name = adapter_name
self._MS = MS

async def __call__(self, file: Union[str, bytes, BytesIO, Path]) -> MessageSegment:
if self.adapter_name == ONEBOT:
self._MS = cast("Type[OneBot_MessageSegment]", self._MS)
self._MS = cast("type[OneBot_MessageSegment]", self._MS)
return self._MS.image(file)

elif self.adapter_name == FEISHU:
# experimental code
self._MS = cast("Type[Feishu_MessageSegment]", self._MS)
self._MS = cast("type[Feishu_MessageSegment]", self._MS)
if isinstance(file, (str, Path)):
with open(file, "rb") as f:
file = f.read()
Expand All @@ -128,7 +129,7 @@ async def __call__(self, file: Union[str, bytes, BytesIO, Path]) -> MessageSegme
return File.photo(file)

elif self.adapter_name == QQGUILD:
self._MS = cast("Type[QQGuild_MessageSegment]", self._MS)
self._MS = cast("type[QQGuild_MessageSegment]", self._MS)

if isinstance(file, str):
return self._MS.image(file)
Expand All @@ -144,9 +145,9 @@ async def __call__(self, file: Union[str, bytes, BytesIO, Path]) -> MessageSegme
raise NotSupportException


def ImageSegmentMethod() -> Callable[
[Union[str, bytes, BytesIO, Path]], Awaitable[MessageSegment]
]:
def ImageSegmentMethod() -> (
Callable[[Union[str, bytes, BytesIO, Path]], Awaitable[MessageSegment]]
):
"""获取 Image Segment 的构造方法。

适配: OneBot, QQGuild
Expand Down
4 changes: 1 addition & 3 deletions nonebot_plugin_params/exception.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
from nonebot.exception import AdapterException


class ValidationError(Exception):
...
class ValidationError(Exception): ...


class NotSupportException(Exception):
Expand Down
3 changes: 2 additions & 1 deletion nonebot_plugin_params/permission.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""提供常用的权限检查。"""

from nonebot.permission import Permission

from .deps import EventName, AdapterName
from .consts import FEISHU, ONEBOT, TELEGRAM
from .deps import AdapterName, EventName


class PrivateMessage:
Expand Down
7 changes: 3 additions & 4 deletions nonebot_plugin_params/rule.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
from typing import Tuple
from typing_extensions import Literal

from nonebot.rule import Rule
from typing_extensions import Literal

from .deps import EventName, AdapterName
from .consts import FEISHU, ONEBOT, QQGUILD, TELEGRAM
from .deps import AdapterName, EventName


class _check_adapter_name:
__slots__ = ("names",)

def __init__(self, names: Tuple[str, ...]) -> None:
def __init__(self, names: tuple[str, ...]) -> None:
self.names = names

async def __call__(self, adapter_name: str = AdapterName()) -> bool:
Expand Down
Loading