mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-12-01 01:25:07 +08:00
🚸 add support of rule to_me
in mirai adapter
This commit is contained in:
parent
5a63827f22
commit
c0fa137fed
@ -13,11 +13,12 @@ from nonebot.exception import ApiNotAvailable, RequestDenied
|
|||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot.message import handle_event
|
from nonebot.message import handle_event
|
||||||
from nonebot.typing import overrides
|
from nonebot.typing import overrides
|
||||||
|
from nonebot.utils import escape_tag
|
||||||
|
|
||||||
from .config import Config as MiraiConfig
|
from .config import Config as MiraiConfig
|
||||||
from .event import Event, FriendMessage, GroupMessage, TempMessage
|
from .event import Event, FriendMessage, GroupMessage, TempMessage
|
||||||
from .message import MessageChain, MessageSegment
|
from .message import MessageChain, MessageSegment
|
||||||
from .utils import catch_network_error, argument_validation
|
from .utils import catch_network_error, argument_validation, check_tome, Log
|
||||||
|
|
||||||
|
|
||||||
class SessionManager:
|
class SessionManager:
|
||||||
@ -209,11 +210,22 @@ class Bot(BaseBot):
|
|||||||
|
|
||||||
@overrides(BaseBot)
|
@overrides(BaseBot)
|
||||||
async def handle_message(self, message: dict):
|
async def handle_message(self, message: dict):
|
||||||
await handle_event(bot=self,
|
Log.debug(f'received message {message}')
|
||||||
event=Event.new({
|
try:
|
||||||
**message,
|
await handle_event(
|
||||||
'self_id': self.self_id,
|
bot=self,
|
||||||
}))
|
event=await check_tome(
|
||||||
|
bot=self,
|
||||||
|
event=Event.new({
|
||||||
|
**message,
|
||||||
|
'self_id': self.self_id,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
logger.opt(colors=True, exception=e).exception(
|
||||||
|
'Failed to handle message '
|
||||||
|
f'<r>{escape_tag(str(message))}</r>: ')
|
||||||
|
|
||||||
@overrides(BaseBot)
|
@overrides(BaseBot)
|
||||||
async def call_api(self, api: str, **data) -> NoReturn:
|
async def call_api(self, api: str, **data) -> NoReturn:
|
||||||
|
@ -80,8 +80,8 @@ class Event(BaseEvent):
|
|||||||
return event_class.parse_obj(data)
|
return event_class.parse_obj(data)
|
||||||
except ValidationError as e:
|
except ValidationError as e:
|
||||||
logger.info(
|
logger.info(
|
||||||
f'Failed to parse {data} to class {event_class.__name__}: {e}. '
|
f'Failed to parse {data} to class {event_class.__name__}: '
|
||||||
'Fallback to parent class.')
|
f'{e.errors()!r}. Fallback to parent class.')
|
||||||
event_class = event_class.__base__
|
event_class = event_class.__base__
|
||||||
|
|
||||||
raise ValueError(f'Failed to serialize {data}.')
|
raise ValueError(f'Failed to serialize {data}.')
|
||||||
|
@ -33,11 +33,20 @@ class MessageEvent(Event):
|
|||||||
class GroupMessage(MessageEvent):
|
class GroupMessage(MessageEvent):
|
||||||
"""群消息事件"""
|
"""群消息事件"""
|
||||||
sender: GroupChatInfo
|
sender: GroupChatInfo
|
||||||
|
to_me: bool = False
|
||||||
|
|
||||||
@overrides(MessageEvent)
|
@overrides(MessageEvent)
|
||||||
def get_session_id(self) -> str:
|
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:
|
||||||
|
return str(self.sender.id)
|
||||||
|
|
||||||
|
@overrides(MessageEvent)
|
||||||
|
def is_tome(self) -> bool:
|
||||||
|
return self.to_me
|
||||||
|
|
||||||
|
|
||||||
class FriendMessage(MessageEvent):
|
class FriendMessage(MessageEvent):
|
||||||
"""好友消息事件"""
|
"""好友消息事件"""
|
||||||
@ -47,15 +56,23 @@ class FriendMessage(MessageEvent):
|
|||||||
def get_user_id(self) -> str:
|
def get_user_id(self) -> str:
|
||||||
return str(self.sender.id)
|
return str(self.sender.id)
|
||||||
|
|
||||||
@overrides
|
@overrides(MessageEvent)
|
||||||
def get_session_id(self) -> str:
|
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:
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class TempMessage(MessageEvent):
|
class TempMessage(MessageEvent):
|
||||||
"""临时会话消息事件"""
|
"""临时会话消息事件"""
|
||||||
sender: GroupChatInfo
|
sender: GroupChatInfo
|
||||||
|
|
||||||
@overrides
|
@overrides(MessageEvent)
|
||||||
def get_session_id(self) -> str:
|
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:
|
||||||
|
return True
|
||||||
|
@ -1,17 +1,44 @@
|
|||||||
|
import re
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from typing import Callable, Coroutine, TypeVar
|
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Optional, TypeVar
|
||||||
|
|
||||||
import httpx
|
import httpx
|
||||||
from pydantic import ValidationError, validate_arguments, Extra
|
from pydantic import Extra, ValidationError, validate_arguments
|
||||||
|
|
||||||
import nonebot.exception as exception
|
import nonebot.exception as exception
|
||||||
from nonebot.log import logger
|
from nonebot.log import logger
|
||||||
from nonebot.utils import escape_tag
|
from nonebot.utils import escape_tag, logger_wrapper
|
||||||
|
|
||||||
|
from .event import Event, GroupMessage
|
||||||
|
from .message import MessageSegment, MessageType
|
||||||
|
|
||||||
|
if TYPE_CHECKING:
|
||||||
|
from .bot import Bot
|
||||||
|
|
||||||
_AsyncCallable = TypeVar("_AsyncCallable", bound=Callable[..., Coroutine])
|
_AsyncCallable = TypeVar("_AsyncCallable", bound=Callable[..., Coroutine])
|
||||||
_AnyCallable = TypeVar("_AnyCallable", bound=Callable)
|
_AnyCallable = TypeVar("_AnyCallable", bound=Callable)
|
||||||
|
|
||||||
|
|
||||||
|
class Log:
|
||||||
|
_log = logger_wrapper('MIRAI')
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def info(cls, message: Any):
|
||||||
|
cls._log('INFO', str(message))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def debug(cls, message: Any):
|
||||||
|
cls._log('DEBUG', str(message))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def warn(cls, message: Any):
|
||||||
|
cls._log('WARNING', str(message))
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def error(cls, message: Any, exception: Optional[Exception] = None):
|
||||||
|
cls._log('ERROR', str(message), exception=exception)
|
||||||
|
|
||||||
|
|
||||||
class ActionFailed(exception.ActionFailed):
|
class ActionFailed(exception.ActionFailed):
|
||||||
"""
|
"""
|
||||||
:说明:
|
:说明:
|
||||||
@ -89,3 +116,41 @@ def argument_validation(function: _AnyCallable) -> _AnyCallable:
|
|||||||
raise InvalidArgument
|
raise InvalidArgument
|
||||||
|
|
||||||
return wrapper # type: ignore
|
return wrapper # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
async def check_tome(bot: "Bot", event: "Event") -> "Event":
|
||||||
|
if not isinstance(event, GroupMessage):
|
||||||
|
return event
|
||||||
|
|
||||||
|
def _is_at(event: GroupMessage) -> bool:
|
||||||
|
for segment in event.message_chain:
|
||||||
|
segment: MessageSegment
|
||||||
|
if segment.type != MessageType.AT:
|
||||||
|
continue
|
||||||
|
if segment.data['target'] == event.self_id:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def _is_nick(event: GroupMessage) -> bool:
|
||||||
|
text = event.get_plaintext()
|
||||||
|
if not text:
|
||||||
|
return False
|
||||||
|
nick_regex = '|'.join(
|
||||||
|
{i.strip() for i in bot.config.nickname if i.strip()})
|
||||||
|
matched = re.search(rf"^({nick_regex})([\s,,]*|$)", text, re.IGNORECASE)
|
||||||
|
if matched is None:
|
||||||
|
return False
|
||||||
|
Log.info(f'User is calling me {matched.group(1)}')
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _is_reply(event: GroupMessage) -> bool:
|
||||||
|
for segment in event.message_chain:
|
||||||
|
segment: MessageSegment
|
||||||
|
if segment.type != MessageType.QUOTE:
|
||||||
|
continue
|
||||||
|
if segment.data['senderId'] == event.self_id:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
event.to_me = any([_is_at(event), _is_reply(event), _is_nick(event)])
|
||||||
|
return event
|
||||||
|
Loading…
Reference in New Issue
Block a user