1
0
forked from bot/app

擴展event字段

This commit is contained in:
远野千束 2024-08-20 20:30:50 +08:00
parent 287ab63091
commit eb7c8300fa
8 changed files with 74 additions and 125 deletions

View File

@ -8,32 +8,57 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
@File : event.py @File : event.py
@Software: PyCharm @Software: PyCharm
""" """
from typing import Any from typing import Any, Optional
from liteyuki.comm.storage import shared_memory from liteyuki.comm.storage import shared_memory
class Event: class MessageEvent:
def __init__(self, type: str, data: dict[str, Any], bot_id: str, session_id: str, session_type: str, receive_channel: str = "event_to_nonebot"): def __init__(
self,
bot_id: str,
message: list[dict[str, Any]] | str,
message_type: str,
raw_message: str,
session_id: str,
session_type: str,
receive_channel: str,
data: Optional[dict[str, Any]] = None,
):
""" """
事件 轻雪抽象消息事件
Args: Args:
type: 类型
data: 数据
bot_id: 机器人ID bot_id: 机器人ID
session_id: 会话ID message: 消息消息段数组[{type: str, data: dict[str, Any]}]
session_type: 会话类型 raw_message: 原始消息(通常为纯文本的格式)
receive_channel: 接收频道 message_type: 消息类型(private, group, other)
session_id: 会话ID(私聊通常为用户ID群聊通常为群ID)
session_type: 会话类型(private, group)
receive_channel: 接收频道(用于回复消息)
data: 附加数据
""" """
self.type = type
if data is None:
data = {}
self.message_type = message_type
self.data = data self.data = data
self.bot_id = bot_id self.bot_id = bot_id
self.message = message
self.raw_message = raw_message
self.session_id = session_id self.session_id = session_id
self.session_type = session_type self.session_type = session_type
self.receive_channel = receive_channel self.receive_channel = receive_channel
def __str__(self): def __str__(self):
return f"Event(type={self.type}, data={self.data}, bot_id={self.bot_id}, session_id={self.session_id}, session_type={self.session_type})" return (f"Event(message_type={self.message_type}, data={self.data}, bot_id={self.bot_id}, "
f"session_id={self.session_id}, session_type={self.session_type})")
def reply(self, message: str | dict[str, Any]): def reply(self, message: str | dict[str, Any]):
""" """
@ -42,8 +67,10 @@ class Event:
message: message:
Returns: Returns:
""" """
to_nonebot_event = Event( reply_event = MessageEvent(
type=self.session_type, message_type=self.session_type,
message=message,
raw_message="",
data={ data={
"message": message "message": message
}, },
@ -52,5 +79,4 @@ class Event:
session_type=self.session_type, session_type=self.session_type,
receive_channel="_" receive_channel="_"
) )
print(to_nonebot_event) shared_memory.publish(self.receive_channel, reply_event)
shared_memory.publish(self.receive_channel, to_nonebot_event)

View File

@ -11,10 +11,10 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
import traceback import traceback
from typing import Any, TypeAlias, Callable, Coroutine from typing import Any, TypeAlias, Callable, Coroutine
from liteyuki import Event from liteyuki.message.event import MessageEvent
from liteyuki.message.rule import Rule from liteyuki.message.rule import Rule
EventHandler: TypeAlias = Callable[[Event], Coroutine[None, None, Any]] EventHandler: TypeAlias = Callable[[MessageEvent], Coroutine[None, None, Any]]
class Matcher: class Matcher:

View File

@ -8,13 +8,12 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
@File : on.py @File : on.py
@Software: PyCharm @Software: PyCharm
""" """
import threading
from queue import Queue from queue import Queue
from liteyuki.comm.storage import shared_memory from liteyuki.comm.storage import shared_memory
from liteyuki.log import logger from liteyuki.log import logger
from liteyuki.message.event import Event from liteyuki.message.event import MessageEvent
from liteyuki.message.matcher import Matcher from liteyuki.message.matcher import Matcher
from liteyuki.message.rule import Rule from liteyuki.message.rule import Rule
@ -23,7 +22,7 @@ _queue: Queue = Queue()
@shared_memory.on_subscriber_receive("event_to_liteyuki") @shared_memory.on_subscriber_receive("event_to_liteyuki")
async def _(event: Event): async def _(event: MessageEvent):
current_priority = -1 current_priority = -1
for i, matcher in enumerate(_matcher_list): for i, matcher in enumerate(_matcher_list):
logger.info(f"Running matcher {matcher} for event: {event}") logger.info(f"Running matcher {matcher} for event: {event}")

View File

@ -11,9 +11,9 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
from typing import Optional, TypeAlias, Callable, Coroutine from typing import Optional, TypeAlias, Callable, Coroutine
from liteyuki.message.event import Event from liteyuki.message.event import MessageEvent
RuleHandler: TypeAlias = Callable[[Event], Coroutine[None, None, bool]] RuleHandler: TypeAlias = Callable[[MessageEvent], Coroutine[None, None, bool]]
"""规则函数签名""" """规则函数签名"""
@ -27,7 +27,7 @@ class Rule:
def __and__(self, other: "Rule") -> "Rule": def __and__(self, other: "Rule") -> "Rule":
return Rule(lambda event: self.handler(event) and other.handler(event)) return Rule(lambda event: self.handler(event) and other.handler(event))
async def __call__(self, event: Event) -> bool: async def __call__(self, event: MessageEvent) -> bool:
if self.handler is None: if self.handler is None:
return True return True
return await self.handler(event) return await self.handler(event)

View File

@ -10,7 +10,7 @@ Copyright (C) 2020-2024 LiteyukiStudio. All Rights Reserved
""" """
from liteyuki.plugin import PluginMetadata, PluginType from liteyuki.plugin import PluginMetadata, PluginType
from liteyuki.message.on import on_message from liteyuki.message.on import on_message
from liteyuki.message.event import Event from liteyuki.message.event import MessageEvent
__plugin_meta__ = PluginMetadata( __plugin_meta__ = PluginMetadata(
name="你好轻雪", name="你好轻雪",
@ -19,6 +19,6 @@ __plugin_meta__ = PluginMetadata(
@on_message().handle @on_message().handle
async def _(event: Event): async def _(event: MessageEvent):
if str(event.data["raw_message"]) == "你好轻雪": if str(event.raw_message) == "你好轻雪":
event.reply("你好呀") event.reply("你好呀")

View File

@ -1,7 +1,6 @@
import nonebot import nonebot
from nonebot.message import event_preprocessor from nonebot.message import event_preprocessor
# from nonebot_plugin_alconna.typings import Event
from src.utils.base.ly_typing import T_MessageEvent from src.utils.base.ly_typing import T_MessageEvent
from src.utils import satori_utils from src.utils import satori_utils
from nonebot.adapters import satori from nonebot.adapters import satori

View File

@ -12,7 +12,7 @@ from nonebot import Bot, get_bot, on_message
from nonebot.plugin import PluginMetadata from nonebot.plugin import PluginMetadata
from nonebot.adapters.onebot.v11 import MessageEvent, Bot from nonebot.adapters.onebot.v11 import MessageEvent, Bot
from liteyuki.comm.storage import shared_memory from liteyuki.comm.storage import shared_memory
from liteyuki.message.event import Event from liteyuki.message.event import MessageEvent as LiteyukiMessageEvent
__plugin_meta__ = PluginMetadata( __plugin_meta__ = PluginMetadata(
name="轻雪物流", name="轻雪物流",
@ -23,8 +23,10 @@ __plugin_meta__ = PluginMetadata(
@on_message().handle() @on_message().handle()
async def _(bot: Bot, event: MessageEvent): async def _(bot: Bot, event: MessageEvent):
liteyuki_event = Event( liteyuki_event = LiteyukiMessageEvent(
type=event.message_type, message_type=event.message_type,
message=event.dict()["message"],
raw_message=event.raw_message,
data=event.dict(), data=event.dict(),
bot_id=bot.self_id, bot_id=bot.self_id,
session_id=str(event.user_id if event.message_type == "private" else event.group_id), session_id=str(event.user_id if event.message_type == "private" else event.group_id),
@ -35,6 +37,6 @@ async def _(bot: Bot, event: MessageEvent):
@shared_memory.on_subscriber_receive("event_to_nonebot") @shared_memory.on_subscriber_receive("event_to_nonebot")
async def _(event: Event): async def _(event: MessageEvent):
bot: Bot = get_bot(event.bot_id) bot: Bot = get_bot(event.bot_id)
await bot.send_msg(message_type=event.type, user_id=int(event.session_id), group_id=int(event.session_id), message=event.data["message"]) await bot.send_msg(message_type=event.message_type, user_id=int(event.session_id), group_id=int(event.session_id), message=event.data["message"])

View File

@ -1,18 +1,15 @@
import base64 import base64
import io import io
from typing import Any
from urllib.parse import quote from urllib.parse import quote
import aiofiles import aiofiles
from PIL import Image
import aiohttp import aiohttp
import nonebot import nonebot
from PIL import Image
from nonebot import require from nonebot import require
from nonebot.adapters import satori from nonebot.adapters import satori
from nonebot.adapters.onebot import v11 from nonebot.adapters.onebot import v11
from typing import Any, Type
from nonebot.internal.adapter import MessageSegment
from nonebot.internal.adapter.message import TM
from .. import load_from_yaml from .. import load_from_yaml
from ..base.ly_typing import T_Bot, T_Message, T_MessageEvent from ..base.ly_typing import T_Bot, T_Message, T_MessageEvent
@ -65,81 +62,18 @@ class MarkdownMessage:
""" """
formatted_md = v11.unescape(markdown).replace("\n", r"\n").replace('"', r'\\\"') formatted_md = v11.unescape(markdown).replace("\n", r"\n").replace('"', r'\\\"')
if event is not None and message_type is None: plain_markdown = formatted_md.replace("[🔗", "[")
if isinstance(event, satori.event.Event): md_image_bytes = await md_to_pic(
message_type = "private" if event.guild is None else "group" md=plain_markdown,
group_id = event.guild.id if event.guild is not None else None width=540,
else: device_scale_factor=4
assert event is not None )
message_type = event.message_type data = await bot.send_msg(
group_id = event.group_id if message_type == "group" else None message_type=message_type,
user_id = event.user.id if isinstance(event, satori.event.Event) else event.user_id group_id=session_id,
session_id = user_id if message_type == "private" else group_id user_id=session_id,
else: message=v11.MessageSegment.image(md_image_bytes),
pass )
try:
raise TencentBannedMarkdownError("Tencent banned markdown")
forward_id = await bot.call_api(
"send_private_forward_msg",
messages=[
{
"type": "node",
"data": {
"content": [
{
"data": {
"content": "{\"content\":\"%s\"}" % formatted_md,
},
"type": "markdown"
}
],
"name": "[]",
"uin": bot.self_id
}
}
],
user_id=bot.self_id
)
data = await bot.send_msg(
user_id=session_id,
group_id=session_id,
message_type=message_type,
message=[
{
"type": "longmsg",
"data": {
"id": forward_id
}
},
],
**kwargs
)
except BaseException as e:
nonebot.logger.error(f"send markdown error, retry as image: {e}")
# 发送失败,渲染为图片发送
# if not retry_as_image:
# return None
plain_markdown = markdown.replace("[🔗", "[")
md_image_bytes = await md_to_pic(
md=plain_markdown,
width=540,
device_scale_factor=4
)
if isinstance(bot, satori.Bot):
msg_seg = satori.MessageSegment.image(raw=md_image_bytes,mime="image/png")
data = await bot.send(
event=event,
message=msg_seg
)
else:
data = await bot.send_msg(
message_type=message_type,
group_id=session_id,
user_id=session_id,
message=v11.MessageSegment.image(md_image_bytes),
)
return data return data
@staticmethod @staticmethod
@ -156,28 +90,17 @@ class MarkdownMessage:
Args: Args:
image: 图片字节流或图片本地路径链接请使用Markdown.image_async方法获取后通过send_md发送 image: 图片字节流或图片本地路径链接请使用Markdown.image_async方法获取后通过send_md发送
bot: bot instance bot: bot instance
message_type: message type message_type: message message_type
session_id: session id session_id: session id
event: event event: event
kwargs: other arguments kwargs: other arguments
Returns: Returns:
dict: response data dict: response data
""" """
if isinstance(image, str): if isinstance(image, str):
async with aiofiles.open(image, "rb") as f: async with aiofiles.open(image, "rb") as f:
image = await f.read() image = await f.read()
method = 2 method = 2
# 1.轻雪图床方案
# if method == 1:
# image_url = await liteyuki_api.upload_image(image)
# image_size = Image.open(io.BytesIO(image)).size
# image_md = Markdown.image(image_url, image_size)
# data = await Markdown.send_md(image_md, bot, message_type=message_type, session_id=session_id, event=event,
# retry_as_image=False,
# **kwargs)
# Lagrange.OneBot方案
if method == 2: if method == 2:
base64_string = base64.b64encode(image).decode("utf-8") base64_string = base64.b64encode(image).decode("utf-8")
data = await bot.call_api("upload_image", file=f"base64://{base64_string}") data = await bot.call_api("upload_image", file=f"base64://{base64_string}")
@ -190,7 +113,7 @@ class MarkdownMessage:
image_message_id = (await bot.send_private_msg( image_message_id = (await bot.send_private_msg(
user_id=bot.self_id, user_id=bot.self_id,
message=[ message=[
v11.MessageSegment.image(file=image) v11.MessageSegment.image(file=image)
] ]
))["message_id"] ))["message_id"]
image_url = (await bot.get_msg(message_id=image_message_id))["message"][0]["data"]["url"] image_url = (await bot.get_msg(message_id=image_message_id))["message"][0]["data"]["url"]