mirror of
https://github.com/nonebot/nonebot2.git
synced 2024-11-24 09:05:04 +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.message import handle_event
|
||||
from nonebot.typing import overrides
|
||||
from nonebot.utils import escape_tag
|
||||
|
||||
from .config import Config as MiraiConfig
|
||||
from .event import Event, FriendMessage, GroupMessage, TempMessage
|
||||
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:
|
||||
@ -209,11 +210,22 @@ class Bot(BaseBot):
|
||||
|
||||
@overrides(BaseBot)
|
||||
async def handle_message(self, message: dict):
|
||||
await handle_event(bot=self,
|
||||
Log.debug(f'received message {message}')
|
||||
try:
|
||||
await handle_event(
|
||||
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)
|
||||
async def call_api(self, api: str, **data) -> NoReturn:
|
||||
|
@ -80,8 +80,8 @@ 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__}: {e}. '
|
||||
'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__
|
||||
|
||||
raise ValueError(f'Failed to serialize {data}.')
|
||||
|
@ -33,11 +33,20 @@ 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()
|
||||
|
||||
@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):
|
||||
"""好友消息事件"""
|
||||
@ -47,15 +56,23 @@ class FriendMessage(MessageEvent):
|
||||
def get_user_id(self) -> str:
|
||||
return str(self.sender.id)
|
||||
|
||||
@overrides
|
||||
@overrides(MessageEvent)
|
||||
def get_session_id(self) -> str:
|
||||
return 'friend_' + self.get_user_id()
|
||||
|
||||
@overrides(MessageEvent)
|
||||
def is_tome(self) -> bool:
|
||||
return True
|
||||
|
||||
|
||||
class TempMessage(MessageEvent):
|
||||
"""临时会话消息事件"""
|
||||
sender: GroupChatInfo
|
||||
|
||||
@overrides
|
||||
@overrides(MessageEvent)
|
||||
def get_session_id(self) -> str:
|
||||
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 typing import Callable, Coroutine, TypeVar
|
||||
from typing import TYPE_CHECKING, Any, Callable, Coroutine, Optional, TypeVar
|
||||
|
||||
import httpx
|
||||
from pydantic import ValidationError, validate_arguments, Extra
|
||||
from pydantic import Extra, ValidationError, validate_arguments
|
||||
|
||||
import nonebot.exception as exception
|
||||
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])
|
||||
_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):
|
||||
"""
|
||||
:说明:
|
||||
@ -89,3 +116,41 @@ def argument_validation(function: _AnyCallable) -> _AnyCallable:
|
||||
raise InvalidArgument
|
||||
|
||||
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