feat: switch Query to langbot-plugin definition

This commit is contained in:
Junyan Qin
2025-06-15 22:04:31 +08:00
parent 0c2560cafb
commit 6b782f8761
88 changed files with 248 additions and 348 deletions
+4 -8
View File
@@ -3,15 +3,14 @@ from __future__ import annotations
# MessageSource的适配器
import typing
import abc
import pydantic
from ..core import app
from .types import message as platform_message
from .types import events as platform_events
from .logger import EventLogger
class MessagePlatformAdapter(metaclass=abc.ABCMeta):
class MessagePlatformAdapter(pydantic.BaseModel, metaclass=abc.ABCMeta):
"""消息平台适配器基类"""
name: str
@@ -21,11 +20,9 @@ class MessagePlatformAdapter(metaclass=abc.ABCMeta):
config: dict
ap: app.Application
logger: EventLogger = pydantic.Field(exclude=True)
logger: EventLogger
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
"""初始化适配器
Args:
@@ -33,7 +30,6 @@ class MessagePlatformAdapter(metaclass=abc.ABCMeta):
ap (app.Application): 应用上下文
"""
self.config = config
self.ap = ap
self.logger = logger
async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain):
+5 -4
View File
@@ -19,6 +19,8 @@ from ..entity.errors import platform as platform_errors
from .logger import EventLogger
import langbot_plugin.api.entities.builtin.provider.session as provider_session
# 处理 3.4 移除了 YiriMirai 之后,插件的兼容性问题
from . import types as mirai
@@ -73,7 +75,7 @@ class RuntimeBot:
await self.ap.query_pool.add_query(
bot_uuid=self.bot_entity.uuid,
launcher_type=core_entities.LauncherTypes.PERSON,
launcher_type=provider_session.LauncherTypes.PERSON,
launcher_id=event.sender.id,
sender_id=event.sender.id,
message_event=event,
@@ -98,7 +100,7 @@ class RuntimeBot:
await self.ap.query_pool.add_query(
bot_uuid=self.bot_entity.uuid,
launcher_type=core_entities.LauncherTypes.GROUP,
launcher_type=provider_session.LauncherTypes.GROUP,
launcher_id=event.group.id,
sender_id=event.sender.id,
message_event=event,
@@ -172,9 +174,9 @@ class PlatformManager:
webchat_logger = EventLogger(name='webchat-adapter', ap=self.ap)
webchat_adapter_inst = webchat_adapter_class(
{},
self.ap,
webchat_logger,
)
webchat_adapter_inst.ap = self.ap
self.webchat_proxy_bot = RuntimeBot(
ap=self.ap,
@@ -231,7 +233,6 @@ class PlatformManager:
adapter_inst = self.adapter_dict[bot_entity.adapter](
bot_entity.adapter_config,
self.ap,
logger,
)
+1 -5
View File
@@ -7,7 +7,6 @@ import datetime
import aiocqhttp
from .. import adapter
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
@@ -273,11 +272,9 @@ class AiocqhttpAdapter(adapter.MessagePlatformAdapter):
config: dict
ap: app.Application
on_websocket_connection_event_cache: typing.List[typing.Callable[[aiocqhttp.Event], None]] = []
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.logger = logger
@@ -287,7 +284,6 @@ class AiocqhttpAdapter(adapter.MessagePlatformAdapter):
self.config['shutdown_trigger'] = shutdown_trigger_placeholder
self.ap = ap
self.on_websocket_connection_event_cache = []
if 'access-token' in config:
+1 -4
View File
@@ -4,7 +4,6 @@ from libs.dingtalk_api.dingtalkevent import DingTalkEvent
from pkg.platform.types import message as platform_message
from pkg.platform.adapter import MessagePlatformAdapter
from .. import adapter
from ...core import app
from ..types import events as platform_events
from ..types import entities as platform_entities
from libs.dingtalk_api.api import DingTalkClient
@@ -94,15 +93,13 @@ class DingTalkEventConverter(adapter.EventConverter):
class DingTalkAdapter(adapter.MessagePlatformAdapter):
bot: DingTalkClient
ap: app.Application
bot_account_id: str
message_converter: DingTalkMessageConverter = DingTalkMessageConverter()
event_converter: DingTalkEventConverter = DingTalkEventConverter()
config: dict
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
required_keys = [
'client_id',
+1 -5
View File
@@ -12,7 +12,6 @@ import datetime
import aiohttp
from .. import adapter
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
@@ -161,8 +160,6 @@ class DiscordAdapter(adapter.MessagePlatformAdapter):
config: dict
ap: app.Application
message_converter: DiscordMessageConverter = DiscordMessageConverter()
event_converter: DiscordEventConverter = DiscordEventConverter()
@@ -171,9 +168,8 @@ class DiscordAdapter(adapter.MessagePlatformAdapter):
typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
] = {}
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
self.bot_account_id = self.config['client_id']
+1 -6
View File
@@ -19,7 +19,6 @@ import quart
from lark_oapi.api.im.v1 import *
from .. import adapter
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
@@ -337,11 +336,9 @@ class LarkAdapter(adapter.MessagePlatformAdapter):
config: dict
quart_app: quart.Quart
ap: app.Application
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
self.quart_app = quart.Quart(__name__)
self.listeners = {}
@@ -351,8 +348,6 @@ class LarkAdapter(adapter.MessagePlatformAdapter):
try:
data = await quart.request.json
self.ap.logger.debug(f'Lark callback event: {data}')
if 'encrypt' in data:
cipher = AESCipher(self.config['encrypt-key'])
data = cipher.decrypt_string(data['encrypt'])

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

@@ -11,16 +11,16 @@ import threading
import quart
import aiohttp
from .. import adapter
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
from ... import adapter
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
import xml.etree.ElementTree as ET
from typing import Optional, Tuple
from functools import partial
from ..logger import EventLogger
from ...logger import EventLogger
class GewechatMessageConverter(adapter.MessageConverter):
@@ -491,7 +491,7 @@ class GeWeChatAdapter(adapter.MessagePlatformAdapter):
async def gewechat_callback():
data = await quart.request.json
# print(json.dumps(data, indent=4, ensure_ascii=False))
self.ap.logger.debug(f'Gewechat callback event: {data}')
await self.logger.debug(f'Gewechat callback event: {data}')
if 'data' in data:
data['Data'] = data['data']
@@ -601,7 +601,7 @@ class GeWeChatAdapter(adapter.MessagePlatformAdapter):
if handler := handler_map.get(msg['type']):
handler(msg)
else:
self.ap.logger.warning(f'未处理的消息类型: {msg["type"]}')
await self.logger.warning(f'未处理的消息类型: {msg["type"]}')
continue
async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain):
@@ -656,9 +656,7 @@ class GeWeChatAdapter(adapter.MessagePlatformAdapter):
self.config['app_id'] = app_id
self.ap.logger.info(f'Gewechat 登录成功,app_id: {app_id}')
self.ap.platform_mgr.write_back_config('gewechat', self, self.config)
print(f'Gewechat 登录成功,app_id: {app_id}')
# 获取 nickname
profile = self.bot.get_profile(self.config['app_id'])

Before

Width:  |  Height:  |  Size: 274 KiB

After

Width:  |  Height:  |  Size: 274 KiB

@@ -9,12 +9,12 @@ import traceback
import nakuru
import nakuru.entities.components as nkc
from .. import adapter as adapter_model
from ...pipeline.longtext.strategies import forward
from ...platform.types import message as platform_message
from ...platform.types import entities as platform_entities
from ...platform.types import events as platform_events
from ..logger import EventLogger
from ... import adapter as adapter_model
from ....pipeline.longtext.strategies import forward
from ...types import message as platform_message
from ...types import entities as platform_entities
from ...types import events as platform_events
from ...logger import EventLogger
class NakuruProjectMessageConverter(adapter_model.MessageConverter):
@@ -262,7 +262,7 @@ class NakuruAdapter(adapter_model.MessagePlatformAdapter):
source_cls = NakuruProjectEventConverter.yiri2target(event_type)
# 包装函数
async def listener_wrapper(app: nakuru.CQHTTP, source: source_cls):
async def listener_wrapper(app: nakuru.CQHTTP, source: source_cls): # type: ignore
await callback(self.event_converter.target2yiri(source), self)
# 将包装函数和原函数的对应关系存入列表
@@ -322,7 +322,6 @@ class NakuruAdapter(adapter_model.MessagePlatformAdapter):
except Exception:
raise Exception('获取go-cqhttp账号信息失败, 请检查是否已启动go-cqhttp并配置正确')
await self.bot._run()
self.ap.logger.info('运行 Nakuru 适配器')
while True:
await asyncio.sleep(1)
@@ -10,14 +10,14 @@ import botpy
import botpy.message as botpy_message
import botpy.types.message as botpy_message_type
from .. import adapter as adapter_model
from ...pipeline.longtext.strategies import forward
from ...core import app
from ...config import manager as cfg_mgr
from ...platform.types import entities as platform_entities
from ...platform.types import events as platform_events
from ...platform.types import message as platform_message
from ..logger import EventLogger
from ... import adapter as adapter_model
from ....pipeline.longtext.strategies import forward
from ....core import app
from ....config import manager as cfg_mgr
from ...types import entities as platform_entities
from ...types import events as platform_events
from ...types import message as platform_message
from ...logger import EventLogger
class OfficialGroupMessage(platform_events.GroupMessage):
@@ -519,7 +519,7 @@ class OfficialAdapter(adapter_model.MessagePlatformAdapter):
self.cfg['ret_coro'] = True
self.ap.logger.info('运行 QQ 官方适配器')
await self.logger.info('运行 QQ 官方适配器')
await (await self.bot.start(**self.cfg))
async def kill(self) -> bool:

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

+1 -4
View File
@@ -10,7 +10,6 @@ from libs.official_account_api.oaevent import OAEvent
from libs.official_account_api.api import OAClient
from libs.official_account_api.api import OAClientForLongerResponse
from .. import adapter
from ...core import app
from ..types import entities as platform_entities
from ...command.errors import ParamNotEnoughError
from ..logger import EventLogger
@@ -58,15 +57,13 @@ class OAEventConverter(adapter.EventConverter):
class OfficialAccountAdapter(adapter.MessagePlatformAdapter):
bot: OAClient | OAClientForLongerResponse
ap: app.Application
bot_account_id: str
message_converter: OAMessageConverter = OAMessageConverter()
event_converter: OAEventConverter = OAEventConverter()
config: dict
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
required_keys = [
+1 -4
View File
@@ -8,7 +8,6 @@ import datetime
from pkg.platform.adapter import MessagePlatformAdapter
from pkg.platform.types import events as platform_events, message as platform_message
from .. import adapter
from ...core import app
from ..types import entities as platform_entities
from ...command.errors import ParamNotEnoughError
from libs.qq_official_api.api import QQOfficialClient
@@ -134,15 +133,13 @@ class QQOfficialEventConverter(adapter.EventConverter):
class QQOfficialAdapter(adapter.MessagePlatformAdapter):
bot: QQOfficialClient
ap: app.Application
config: dict
bot_account_id: str
message_converter: QQOfficialMessageConverter = QQOfficialMessageConverter()
event_converter: QQOfficialEventConverter = QQOfficialEventConverter()
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
required_keys = [
+1 -4
View File
@@ -9,7 +9,6 @@ from libs.slack_api.api import SlackClient
from pkg.platform.adapter import MessagePlatformAdapter
from pkg.platform.types import events as platform_events, message as platform_message
from libs.slack_api.slackevent import SlackEvent
from pkg.core import app
from .. import adapter
from ..types import entities as platform_entities
from ...command.errors import ParamNotEnoughError
@@ -86,15 +85,13 @@ class SlackEventConverter(adapter.EventConverter):
class SlackAdapter(adapter.MessagePlatformAdapter):
bot: SlackClient
ap: app.Application
bot_account_id: str
message_converter: SlackMessageConverter = SlackMessageConverter()
event_converter: SlackEventConverter = SlackEventConverter()
config: dict
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
required_keys = [
'bot_token',
+1 -6
View File
@@ -10,10 +10,7 @@ import traceback
import base64
import aiohttp
from lark_oapi.api.im.v1 import *
from .. import adapter
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
@@ -141,16 +138,14 @@ class TelegramAdapter(adapter.MessagePlatformAdapter):
event_converter: TelegramEventConverter = TelegramEventConverter()
config: dict
ap: app.Application
listeners: typing.Dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
] = {}
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
async def telegram_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
+3 -2
View File
@@ -44,13 +44,14 @@ class WebChatAdapter(msadapter.MessagePlatformAdapter):
webchat_person_session: WebChatSession
webchat_group_session: WebChatSession
ap: app.Application # set by bot manager
listeners: typing.Dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, msadapter.MessagePlatformAdapter], None],
] = {}
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
self.ap = ap
def __init__(self, config: dict, logger: EventLogger):
self.logger = logger
self.config = config
+11 -16
View File
@@ -488,6 +488,8 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
ap: app.Application
logger: EventLogger
message_converter: WeChatPadMessageConverter
event_converter: WeChatPadEventConverter
@@ -507,8 +509,6 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
async def ws_message(self, data):
"""处理接收到的消息"""
# self.ap.logger.debug(f"Gewechat callback event: {data}")
# print(data)
try:
event = await self.event_converter.target2yiri(data.copy(), self.bot_account_id)
@@ -571,9 +571,8 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
if handler := handler_map.get(msg['type']):
handler(msg)
# self.ap.logger.warning(f"未处理的消息类型: {ret}")
else:
self.ap.logger.warning(f'未处理的消息类型: {msg["type"]}')
print(f'未处理的消息类型: {msg["type"]}')
continue
async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain):
@@ -615,7 +614,6 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
if self.config['token']:
self.bot = WeChatPadClient(self.config['wechatpad_url'], self.config['token'])
data = self.bot.get_login_status()
self.ap.logger.info(data)
if data['Code'] == 300 and data['Text'] == '你已退出微信':
response = requests.post(
f'{self.config["wechatpad_url"]}/admin/GenAuthKey1?key={self.config["admin_key"]}',
@@ -635,7 +633,7 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
self.config['token'] = response.json()['Data'][0]
self.bot = WeChatPadClient(self.config['wechatpad_url'], self.config['token'], logger=self.logger)
self.ap.logger.info(self.config['token'])
await self.logger.info(self.config['token'])
thread_1 = threading.Event()
def wechat_login_process():
@@ -643,10 +641,9 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
# login_data =self.bot.get_login_qr()
# url = login_data['Data']["QrCodeUrl"]
# self.ap.logger.info(login_data)
profile = self.bot.get_profile()
self.ap.logger.info(profile)
self.logger.info(profile)
self.bot_account_id = profile['Data']['userInfo']['nickName']['str']
self.config['wxid'] = profile['Data']['userInfo']['userName']['str']
@@ -658,27 +655,26 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
def connect_websocket_sync() -> None:
thread_1.wait()
uri = f'{self.config["wechatpad_ws"]}/GetSyncMsg?key={self.config["token"]}'
self.ap.logger.info(f'Connecting to WebSocket: {uri}')
print(f'Connecting to WebSocket: {uri}')
def on_message(ws, message):
try:
data = json.loads(message)
self.ap.logger.debug(f'Received message: {data}')
# 这里需要确保ws_message是同步的,或者使用asyncio.run调用异步方法
asyncio.run(self.ws_message(data))
except json.JSONDecodeError:
self.ap.logger.error(f'Non-JSON message: {message[:100]}...')
print(f'Non-JSON message: {message[:100]}...')
def on_error(ws, error):
self.ap.logger.error(f'WebSocket error: {str(error)[:200]}')
print(f'WebSocket error: {str(error)[:200]}')
def on_close(ws, close_status_code, close_msg):
self.ap.logger.info('WebSocket closed, reconnecting...')
print('WebSocket closed, reconnecting...')
time.sleep(5)
connect_websocket_sync() # 自动重连
def on_open(ws):
self.ap.logger.info('WebSocket connected successfully!')
print('WebSocket connected successfully!')
ws = websocket.WebSocketApp(
uri, on_message=on_message, on_error=on_error, on_close=on_close, on_open=on_open
@@ -689,10 +685,9 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
# connect_websocket_sync()
# 这行代码会在WebSocket连接断开后才会执行
# self.ap.logger.info("WebSocket client thread started")
thread = threading.Thread(target=connect_websocket_sync, name='WebSocketClientThread', daemon=True)
thread.start()
self.ap.logger.info('WebSocket client thread started')
self.logger.info('WebSocket client thread started')
async def kill(self) -> bool:
pass
+1 -4
View File
@@ -10,7 +10,6 @@ from pkg.platform.adapter import MessagePlatformAdapter
from pkg.platform.types import events as platform_events, message as platform_message
from libs.wecom_api.wecomevent import WecomEvent
from .. import adapter
from ...core import app
from ..types import entities as platform_entities
from ...command.errors import ParamNotEnoughError
from ...utils import image
@@ -129,15 +128,13 @@ class WecomEventConverter:
class WecomAdapter(adapter.MessagePlatformAdapter):
bot: WecomClient
ap: app.Application
bot_account_id: str
message_converter: WecomMessageConverter = WecomMessageConverter()
event_converter: WecomEventConverter = WecomEventConverter()
config: dict
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
required_keys = [
+1 -4
View File
@@ -9,7 +9,6 @@ from libs.wecom_customer_service_api.api import WecomCSClient
from pkg.platform.adapter import MessagePlatformAdapter
from pkg.platform.types import events as platform_events, message as platform_message
from libs.wecom_customer_service_api.wecomcsevent import WecomCSEvent
from pkg.core import app
from .. import adapter
from ..types import entities as platform_entities
from ...command.errors import ParamNotEnoughError
@@ -119,15 +118,13 @@ class WecomEventConverter:
class WecomCSAdapter(adapter.MessagePlatformAdapter):
bot: WecomCSClient
ap: app.Application
bot_account_id: str
message_converter: WecomMessageConverter = WecomMessageConverter()
event_converter: WecomEventConverter = WecomEventConverter()
config: dict
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.ap = ap
self.logger = logger
required_keys = [