Files
LangBot/pkg/platform/sources/aiocqhttp.py

302 lines
11 KiB
Python
Raw Normal View History

2024-02-07 20:03:46 +08:00
from __future__ import annotations
import typing
import asyncio
import traceback
import time
import datetime
import aiocqhttp
import aiohttp
2024-02-07 20:03:46 +08:00
from .. import adapter
from ...pipeline.longtext.strategies import forward
from ...core import app
from ..types import message as platform_message
from ..types import events as platform_events
from ..types import entities as platform_entities
from ...utils import image
2024-02-07 20:03:46 +08:00
class AiocqhttpMessageConverter(adapter.MessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain) -> typing.Tuple[list, int, datetime.datetime]:
2024-02-07 20:03:46 +08:00
msg_list = aiocqhttp.Message()
msg_id = 0
msg_time = None
for msg in message_chain:
if type(msg) is platform_message.Plain:
2024-02-07 20:03:46 +08:00
msg_list.append(aiocqhttp.MessageSegment.text(msg.text))
elif type(msg) is platform_message.Source:
2024-02-07 20:03:46 +08:00
msg_id = msg.id
msg_time = msg.time
elif type(msg) is platform_message.Image:
arg = ''
2024-05-17 17:05:20 +08:00
if msg.base64:
arg = msg.base64
msg_list.append(aiocqhttp.MessageSegment.image(f"base64://{arg}"))
elif msg.url:
arg = msg.url
msg_list.append(aiocqhttp.MessageSegment.image(arg))
elif msg.path:
arg = msg.path
msg_list.append(aiocqhttp.MessageSegment.image(arg))
elif type(msg) is platform_message.At:
2024-02-07 20:03:46 +08:00
msg_list.append(aiocqhttp.MessageSegment.at(msg.target))
elif type(msg) is platform_message.AtAll:
2024-02-07 20:03:46 +08:00
msg_list.append(aiocqhttp.MessageSegment.at("all"))
elif type(msg) is platform_message.Voice:
arg = ''
if msg.base64:
arg = msg.base64
msg_list.append(aiocqhttp.MessageSegment.record(f"base64://{arg}"))
elif msg.url:
arg = msg.url
msg_list.append(aiocqhttp.MessageSegment.record(arg))
elif msg.path:
arg = msg.path
msg_list.append(aiocqhttp.MessageSegment.record(msg.path))
2024-02-07 20:03:46 +08:00
elif type(msg) is forward.Forward:
for node in msg.node_list:
2024-12-24 23:37:02 +08:00
msg_list.extend((await AiocqhttpMessageConverter.yiri2target(node.message_chain))[0])
2024-02-07 20:03:46 +08:00
else:
msg_list.append(aiocqhttp.MessageSegment.text(str(msg)))
return msg_list, msg_id, msg_time
@staticmethod
async def target2yiri(message: str, message_id: int = -1):
2024-02-07 20:03:46 +08:00
message = aiocqhttp.Message(message)
yiri_msg_list = []
yiri_msg_list.append(
platform_message.Source(id=message_id, time=datetime.datetime.now())
2024-02-07 20:03:46 +08:00
)
for msg in message:
if msg.type == "at":
if msg.data["qq"] == "all":
yiri_msg_list.append(platform_message.AtAll())
2024-02-07 20:03:46 +08:00
else:
yiri_msg_list.append(
platform_message.At(
2024-02-07 20:03:46 +08:00
target=msg.data["qq"],
)
)
elif msg.type == "text":
yiri_msg_list.append(platform_message.Plain(text=msg.data["text"]))
2024-02-07 20:03:46 +08:00
elif msg.type == "image":
image_base64, image_format = await image.qq_image_url_to_base64(msg.data['url'])
yiri_msg_list.append(platform_message.Image(base64=f"data:image/{image_format};base64,{image_base64}"))
2024-02-07 20:03:46 +08:00
chain = platform_message.MessageChain(yiri_msg_list)
2024-02-07 20:03:46 +08:00
return chain
class AiocqhttpEventConverter(adapter.EventConverter):
@staticmethod
async def yiri2target(event: platform_events.Event, bot_account_id: int):
2024-02-07 20:03:46 +08:00
msg, msg_id, msg_time = await AiocqhttpMessageConverter.yiri2target(event.message_chain)
2024-02-07 20:03:46 +08:00
if type(event) is platform_events.GroupMessage:
2024-02-07 20:03:46 +08:00
role = "member"
if event.sender.permission == "ADMINISTRATOR":
role = "admin"
elif event.sender.permission == "OWNER":
role = "owner"
payload = {
"post_type": "message",
"message_type": "group",
"time": int(msg_time.timestamp()),
"self_id": bot_account_id,
"sub_type": "normal",
"anonymous": None,
"font": 0,
"message": str(msg),
"raw_message": str(msg),
"sender": {
"age": 0,
"area": "",
"card": "",
"level": "",
"nickname": event.sender.member_name,
"role": role,
"sex": "unknown",
"title": "",
"user_id": event.sender.id,
},
"user_id": event.sender.id,
"message_id": msg_id,
"group_id": event.group.id,
"message_seq": 0,
}
return aiocqhttp.Event.from_payload(payload)
elif type(event) is platform_events.FriendMessage:
2024-02-07 20:03:46 +08:00
payload = {
"post_type": "message",
"message_type": "private",
"time": int(msg_time.timestamp()),
"self_id": bot_account_id,
"sub_type": "friend",
"target_id": bot_account_id,
"message": str(msg),
"raw_message": str(msg),
"font": 0,
"sender": {
"age": 0,
"nickname": event.sender.nickname,
"sex": "unknown",
"user_id": event.sender.id,
},
"message_id": msg_id,
"user_id": event.sender.id,
}
return aiocqhttp.Event.from_payload(payload)
@staticmethod
async def target2yiri(event: aiocqhttp.Event):
yiri_chain = await AiocqhttpMessageConverter.target2yiri(
2024-02-07 20:03:46 +08:00
event.message, event.message_id
)
if event.message_type == "group":
permission = "MEMBER"
if "role" in event.sender:
if event.sender["role"] == "admin":
permission = "ADMINISTRATOR"
elif event.sender["role"] == "owner":
permission = "OWNER"
converted_event = platform_events.GroupMessage(
sender=platform_entities.GroupMember(
2024-02-07 20:03:46 +08:00
id=event.sender["user_id"], # message_seq 放哪?
member_name=event.sender["nickname"],
permission=permission,
group=platform_entities.Group(
2024-02-07 20:03:46 +08:00
id=event.group_id,
name=event.sender["nickname"],
permission=platform_entities.Permission.Member,
2024-02-07 20:03:46 +08:00
),
special_title=event.sender["title"] if "title" in event.sender else "",
2024-02-07 20:03:46 +08:00
join_timestamp=0,
last_speak_timestamp=0,
mute_time_remaining=0,
),
message_chain=yiri_chain,
time=event.time,
)
return converted_event
elif event.message_type == "private":
return platform_events.FriendMessage(
sender=platform_entities.Friend(
2024-02-07 20:03:46 +08:00
id=event.sender["user_id"],
nickname=event.sender["nickname"],
remark="",
),
message_chain=yiri_chain,
time=event.time,
)
2024-02-08 13:12:33 +08:00
@adapter.adapter_class("aiocqhttp")
2024-02-07 20:03:46 +08:00
class AiocqhttpAdapter(adapter.MessageSourceAdapter):
bot: aiocqhttp.CQHttp
bot_account_id: int
message_converter: AiocqhttpMessageConverter = AiocqhttpMessageConverter()
event_converter: AiocqhttpEventConverter = AiocqhttpEventConverter()
config: dict
ap: app.Application
def __init__(self, config: dict, ap: app.Application):
self.config = config
2024-02-15 22:21:56 +08:00
async def shutdown_trigger_placeholder():
while True:
await asyncio.sleep(1)
2024-02-15 22:21:56 +08:00
self.config['shutdown_trigger'] = shutdown_trigger_placeholder
2024-02-07 20:03:46 +08:00
self.ap = ap
if "access-token" in config:
2024-03-13 16:49:11 +08:00
self.bot = aiocqhttp.CQHttp(access_token=config["access-token"])
del self.config["access-token"]
else:
self.bot = aiocqhttp.CQHttp()
2024-02-07 20:03:46 +08:00
async def send_message(
self, target_type: str, target_id: str, message: platform_message.MessageChain
2024-02-07 20:03:46 +08:00
):
2024-12-24 23:37:02 +08:00
aiocq_msg = (await AiocqhttpMessageConverter.yiri2target(message))[0]
if target_type == "group":
await self.bot.send_group_msg(group_id=int(target_id), message=aiocq_msg)
elif target_type == "person":
await self.bot.send_private_msg(user_id=int(target_id), message=aiocq_msg)
2024-02-07 20:03:46 +08:00
async def reply_message(
self,
message_source: platform_events.MessageEvent,
message: platform_message.MessageChain,
2024-02-07 20:03:46 +08:00
quote_origin: bool = False,
):
aiocq_event = await AiocqhttpEventConverter.yiri2target(message_source, self.bot_account_id)
aiocq_msg = (await AiocqhttpMessageConverter.yiri2target(message))[0]
2024-02-07 20:03:46 +08:00
if quote_origin:
aiocq_msg = aiocqhttp.MessageSegment.reply(aiocq_event.message_id) + aiocq_msg
return await self.bot.send(
aiocq_event,
aiocq_msg
)
async def is_muted(self, group_id: int) -> bool:
return False
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessageSourceAdapter], None],
2024-02-07 20:03:46 +08:00
):
async def on_message(event: aiocqhttp.Event):
self.bot_account_id = event.self_id
try:
return await callback(await self.event_converter.target2yiri(event), self)
2024-02-07 20:03:46 +08:00
except:
traceback.print_exc()
if event_type == platform_events.GroupMessage:
2024-02-07 20:03:46 +08:00
self.bot.on_message("group")(on_message)
elif event_type == platform_events.FriendMessage:
2024-02-07 20:03:46 +08:00
self.bot.on_message("private")(on_message)
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessageSourceAdapter], None],
2024-02-07 20:03:46 +08:00
):
return super().unregister_listener(event_type, callback)
async def run_async(self):
await self.bot._server_app.run_task(**self.config)
async def kill(self) -> bool:
return False