feat: switch message platform adapters to sdk

This commit is contained in:
Junyan Qin
2025-06-16 13:18:59 +08:00
parent 62b2884011
commit a177786063
51 changed files with 361 additions and 1763 deletions

View File

@@ -5,16 +5,17 @@ import traceback
import datetime
import aiocqhttp
import pydantic
from .. import adapter
from ..types import message as platform_message
from ..types import events as platform_events
from ..types import entities as platform_entities
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
from ...utils import image
from ..logger import EventLogger
import langbot_plugin.api.definition.abstract.platform.event_logger as abstract_platform_logger
class AiocqhttpMessageConverter(adapter.MessageConverter):
class AiocqhttpMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(
message_chain: platform_message.MessageChain,
@@ -69,7 +70,6 @@ class AiocqhttpMessageConverter(adapter.MessageConverter):
elif msg.face_type=='dice':
msg_list.append(aiocqhttp.MessageSegment.dice())
else:
msg_list.append(aiocqhttp.MessageSegment.text(str(msg)))
@@ -190,6 +190,7 @@ class AiocqhttpMessageConverter(adapter.MessageConverter):
file_data = await bot.get_file(file_id=file_id)
file_name = file_data.get('file_name')
file_path = file_data.get('file')
_ = file_path
file_url = file_data.get('file_url')
file_size = file_data.get('file_size')
yiri_msg_list.append(platform_message.File(id=file_id, name=file_name,url=file_url,size=file_size))
@@ -211,7 +212,7 @@ class AiocqhttpMessageConverter(adapter.MessageConverter):
return chain
class AiocqhttpEventConverter(adapter.EventConverter):
class AiocqhttpEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.MessageEvent, bot_account_id: int):
return event.source_platform_object
@@ -262,21 +263,19 @@ class AiocqhttpEventConverter(adapter.EventConverter):
)
class AiocqhttpAdapter(adapter.MessagePlatformAdapter):
bot: aiocqhttp.CQHttp
bot_account_id: int
class AiocqhttpAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: aiocqhttp.CQHttp = pydantic.Field(exclude=True, default_factory=aiocqhttp.CQHttp)
message_converter: AiocqhttpMessageConverter = AiocqhttpMessageConverter()
event_converter: AiocqhttpEventConverter = AiocqhttpEventConverter()
config: dict
on_websocket_connection_event_cache: typing.List[typing.Callable[[aiocqhttp.Event], None]] = []
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.logger = logger
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger):
super().__init__(
config=config,
logger=logger,
)
async def shutdown_trigger_placeholder():
while True:
@@ -296,7 +295,6 @@ class AiocqhttpAdapter(adapter.MessagePlatformAdapter):
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)
@@ -320,7 +318,9 @@ class AiocqhttpAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
async def on_message(event: aiocqhttp.Event):
self.bot_account_id = event.self_id
@@ -351,7 +351,9 @@ class AiocqhttpAdapter(adapter.MessagePlatformAdapter):
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
return super().unregister_listener(event_type, callback)

View File

@@ -1,17 +1,16 @@
import traceback
import typing
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 ..types import events as platform_events
from ..types import entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
from libs.dingtalk_api.api import DingTalkClient
import datetime
from ..logger import EventLogger
class DingTalkMessageConverter(adapter.MessageConverter):
class DingTalkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain):
content = ''
@@ -47,7 +46,7 @@ class DingTalkMessageConverter(adapter.MessageConverter):
return chain
class DingTalkEventConverter(adapter.EventConverter):
class DingTalkEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.MessageEvent):
return event.source_platform_object
@@ -91,7 +90,7 @@ class DingTalkEventConverter(adapter.EventConverter):
)
class DingTalkAdapter(adapter.MessagePlatformAdapter):
class DingTalkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: DingTalkClient
bot_account_id: str
message_converter: DingTalkMessageConverter = DingTalkMessageConverter()
@@ -137,7 +136,9 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
async def on_message(event: DingTalkEvent):
try:
@@ -171,6 +172,8 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter):
async def unregister_listener(
self,
event_type: type,
callback: typing.Callable[[platform_events.Event, MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
return super().unregister_listener(event_type, callback)

View File

@@ -10,15 +10,16 @@ import os
import datetime
import aiohttp
import pydantic
from .. import adapter
from ..types import message as platform_message
from ..types import events as platform_events
from ..types import entities as platform_entities
from ..logger import EventLogger
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.definition.abstract.platform.event_logger as abstract_platform_logger
class DiscordMessageConverter(adapter.MessageConverter):
class DiscordMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(
message_chain: platform_message.MessageChain,
@@ -111,7 +112,7 @@ class DiscordMessageConverter(adapter.MessageConverter):
return platform_message.MessageChain(element_list)
class DiscordEventConverter(adapter.EventConverter):
class DiscordEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.Event) -> discord.Message:
pass
@@ -153,26 +154,21 @@ class DiscordEventConverter(adapter.EventConverter):
)
class DiscordAdapter(adapter.MessagePlatformAdapter):
bot: discord.Client
bot_account_id: str # 用于在流水线中识别at是否是本bot直接以bot_name作为标识
config: dict
class DiscordAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: discord.Client = pydantic.Field(exclude=True)
message_converter: DiscordMessageConverter = DiscordMessageConverter()
event_converter: DiscordEventConverter = DiscordEventConverter()
listeners: typing.Dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
] = {}
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.logger = logger
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger):
bot_account_id = config['client_id']
self.bot_account_id = self.config['client_id']
listeners = {}
adapter_self = self
@@ -192,7 +188,15 @@ class DiscordAdapter(adapter.MessagePlatformAdapter):
if os.getenv('http_proxy'):
args['proxy'] = os.getenv('http_proxy')
self.bot = MyClient(intents=intents, **args)
bot = MyClient(intents=intents, **args)
super().__init__(
config=config,
logger=logger,
bot_account_id=bot_account_id,
listeners=listeners,
bot=bot,
)
async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain):
pass
@@ -227,14 +231,18 @@ class DiscordAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners[event_type] = callback
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners.pop(event_type)

View File

@@ -17,12 +17,13 @@ import aiohttp
import lark_oapi.ws.exception
import quart
from lark_oapi.api.im.v1 import *
import pydantic
from .. import adapter
from ..types import message as platform_message
from ..types import events as platform_events
from ..types import entities as platform_entities
from ..logger import EventLogger
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.definition.abstract.platform.event_logger as abstract_platform_logger
class AESCipher(object):
@@ -51,7 +52,7 @@ class AESCipher(object):
return self.decrypt(enc).decode('utf8')
class LarkMessageConverter(adapter.MessageConverter):
class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(
message_chain: platform_message.MessageChain, api_client: lark_oapi.Client
@@ -275,7 +276,7 @@ class LarkMessageConverter(adapter.MessageConverter):
return platform_message.MessageChain(lb_msg_list)
class LarkEventConverter(adapter.EventConverter):
class LarkEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(
event: platform_events.MessageEvent,
@@ -319,31 +320,24 @@ class LarkEventConverter(adapter.EventConverter):
)
class LarkAdapter(adapter.MessagePlatformAdapter):
bot: lark_oapi.ws.Client
api_client: lark_oapi.Client
bot_account_id: str # 用于在流水线中识别at是否是本bot直接以bot_name作为标识
lark_tenant_key: str # 飞书企业key
class LarkAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: lark_oapi.ws.Client = pydantic.Field(exclude=True)
api_client: lark_oapi.Client = pydantic.Field(exclude=True)
message_converter: LarkMessageConverter = LarkMessageConverter()
event_converter: LarkEventConverter = LarkEventConverter()
listeners: typing.Dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
]
config: dict
quart_app: quart.Quart
quart_app: quart.Quart = pydantic.Field(exclude=True)
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.logger = logger
self.quart_app = quart.Quart(__name__)
self.listeners = {}
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger):
quart_app = quart.Quart(__name__)
@self.quart_app.route('/lark/callback', methods=['POST'])
@quart_app.route('/lark/callback', methods=['POST'])
async def lark_callback():
try:
data = await quart.request.json
@@ -396,10 +390,20 @@ class LarkAdapter(adapter.MessagePlatformAdapter):
lark_oapi.EventDispatcherHandler.builder('', '').register_p2_im_message_receive_v1(sync_on_message).build()
)
self.bot_account_id = config['bot_name']
bot_account_id = config['bot_name']
self.bot = lark_oapi.ws.Client(config['app_id'], config['app_secret'], event_handler=event_handler)
self.api_client = lark_oapi.Client.builder().app_id(config['app_id']).app_secret(config['app_secret']).build()
bot = lark_oapi.ws.Client(config['app_id'], config['app_secret'], event_handler=event_handler)
api_client = lark_oapi.Client.builder().app_id(config['app_id']).app_secret(config['app_secret']).build()
super().__init__(
config=config,
logger=logger,
listeners={},
quart_app=quart_app,
bot=bot,
api_client=api_client,
bot_account_id=bot_account_id,
)
async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain):
pass
@@ -448,14 +452,18 @@ class LarkAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners[event_type] = callback
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners.pop(event_type)

View File

@@ -11,11 +11,11 @@ import threading
import quart
import aiohttp
from ... import adapter
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_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
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
from ....utils import image
import xml.etree.ElementTree as ET
from typing import Optional, Tuple
@@ -23,7 +23,7 @@ from functools import partial
from ...logger import EventLogger
class GewechatMessageConverter(adapter.MessageConverter):
class GewechatMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
def __init__(self, config: dict):
self.config = config
@@ -398,7 +398,7 @@ class GewechatMessageConverter(adapter.MessageConverter):
return from_user_name.endswith('@chatroom')
class GewechatEventConverter(adapter.EventConverter):
class GewechatEventConverter(abstract_platform_adapter.AbstractEventConverter):
def __init__(self, config: dict):
self.config = config
self.message_converter = GewechatMessageConverter(config)
@@ -458,7 +458,7 @@ class GewechatEventConverter(adapter.EventConverter):
)
class GeWeChatAdapter(adapter.MessagePlatformAdapter):
class GeWeChatAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
name: str = 'gewechat' # 定义适配器名称
bot: gewechat_client.GewechatClient
@@ -475,7 +475,7 @@ class GeWeChatAdapter(adapter.MessagePlatformAdapter):
listeners: typing.Dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
] = {}
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
@@ -625,14 +625,18 @@ class GeWeChatAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners[event_type] = callback
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
pass

View File

@@ -9,15 +9,15 @@ import traceback
import nakuru
import nakuru.entities.components as nkc
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
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
from ...logger import EventLogger
class NakuruProjectMessageConverter(adapter_model.MessageConverter):
class NakuruProjectMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
"""消息转换器"""
@staticmethod
@@ -109,7 +109,7 @@ class NakuruProjectMessageConverter(adapter_model.MessageConverter):
return chain
class NakuruProjectEventConverter(adapter_model.EventConverter):
class NakuruProjectEventConverter(abstract_platform_adapter.AbstractEventConverter):
"""事件转换器"""
@staticmethod
@@ -164,7 +164,7 @@ class NakuruProjectEventConverter(adapter_model.EventConverter):
raise Exception('未支持转换的事件类型: ' + str(event))
class NakuruAdapter(adapter_model.MessagePlatformAdapter):
class NakuruAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
"""nakuru-project适配器"""
bot: nakuru.CQHTTP
@@ -256,7 +256,9 @@ class NakuruAdapter(adapter_model.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter_model.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
try:
source_cls = NakuruProjectEventConverter.yiri2target(event_type)
@@ -283,7 +285,9 @@ class NakuruAdapter(adapter_model.MessagePlatformAdapter):
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter_model.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
nakuru_event_name = self.event_converter.yiri2target(event_type).__name__

View File

@@ -10,13 +10,13 @@ import botpy
import botpy.message as botpy_message
import botpy.types.message as botpy_message_type
from ... import adapter as adapter_model
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
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
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.message as platform_message
from ...logger import EventLogger
@@ -133,7 +133,7 @@ class OpenIDMapping(typing.Generic[K, V]):
return value
class OfficialMessageConverter(adapter_model.MessageConverter):
class OfficialMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
"""QQ 官方消息转换器"""
@staticmethod
@@ -237,7 +237,7 @@ class OfficialMessageConverter(adapter_model.MessageConverter):
return chain
class OfficialEventConverter(adapter_model.EventConverter):
class OfficialEventConverter(abstract_platform_adapter.AbstractEventConverter):
"""事件转换器"""
def __init__(self):
@@ -333,7 +333,7 @@ class OfficialEventConverter(adapter_model.EventConverter):
)
class OfficialAdapter(adapter_model.MessagePlatformAdapter):
class OfficialAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
"""QQ 官方消息适配器"""
bot: botpy.Client = None
@@ -484,7 +484,9 @@ class OfficialAdapter(adapter_model.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter_model.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
try:
@@ -507,7 +509,9 @@ class OfficialAdapter(adapter_model.MessagePlatformAdapter):
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter_model.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
delattr(self.bot, event_handler_mapping[event_type])

View File

@@ -4,18 +4,18 @@ import asyncio
import traceback
import datetime
from pkg.platform.adapter import MessagePlatformAdapter
from pkg.platform.types import events as platform_events, message as platform_message
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
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 ..types import entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
from ...command.errors import ParamNotEnoughError
from ..logger import EventLogger
class OAMessageConverter(adapter.MessageConverter):
class OAMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain):
for msg in message_chain:
@@ -33,7 +33,7 @@ class OAMessageConverter(adapter.MessageConverter):
return chain
class OAEventConverter(adapter.EventConverter):
class OAEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def target2yiri(event: OAEvent):
if event.type == 'text':
@@ -55,7 +55,7 @@ class OAEventConverter(adapter.EventConverter):
return None
class OfficialAccountAdapter(adapter.MessagePlatformAdapter):
class OfficialAccountAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: OAClient | OAClientForLongerResponse
bot_account_id: str
message_converter: OAMessageConverter = OAMessageConverter()
@@ -116,7 +116,9 @@ class OfficialAccountAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: type,
callback: typing.Callable[[platform_events.Event, MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
async def on_message(event: OAEvent):
self.bot_account_id = event.receiver_id
@@ -147,6 +149,8 @@ class OfficialAccountAdapter(adapter.MessagePlatformAdapter):
async def unregister_listener(
self,
event_type: type,
callback: typing.Callable[[platform_events.Event, MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
return super().unregister_listener(event_type, callback)

View File

@@ -5,10 +5,10 @@ import traceback
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 ..types import entities as platform_entities
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
from ...command.errors import ParamNotEnoughError
from libs.qq_official_api.api import QQOfficialClient
from libs.qq_official_api.qqofficialevent import QQOfficialEvent
@@ -16,7 +16,7 @@ from ...utils import image
from ..logger import EventLogger
class QQOfficialMessageConverter(adapter.MessageConverter):
class QQOfficialMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain):
content_list = []
@@ -45,7 +45,7 @@ class QQOfficialMessageConverter(adapter.MessageConverter):
return chain
class QQOfficialEventConverter(adapter.EventConverter):
class QQOfficialEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.MessageEvent) -> QQOfficialEvent:
return event.source_platform_object
@@ -131,7 +131,7 @@ class QQOfficialEventConverter(adapter.EventConverter):
)
class QQOfficialAdapter(adapter.MessagePlatformAdapter):
class QQOfficialAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: QQOfficialClient
config: dict
bot_account_id: str
@@ -212,7 +212,9 @@ class QQOfficialAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
async def on_message(event: QQOfficialEvent):
self.bot_account_id = 'justbot'
@@ -245,6 +247,8 @@ class QQOfficialAdapter(adapter.MessagePlatformAdapter):
def unregister_listener(
self,
event_type: type,
callback: typing.Callable[[platform_events.Event, MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
return super().unregister_listener(event_type, callback)

View File

@@ -6,17 +6,17 @@ import traceback
import datetime
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
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
from libs.slack_api.slackevent import SlackEvent
from .. import adapter
from ..types import entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
from ...command.errors import ParamNotEnoughError
from ...utils import image
from ..logger import EventLogger
class SlackMessageConverter(adapter.MessageConverter):
class SlackMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain):
content_list = []
@@ -43,7 +43,7 @@ class SlackMessageConverter(adapter.MessageConverter):
return chain
class SlackEventConverter(adapter.EventConverter):
class SlackEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.MessageEvent) -> SlackEvent:
return event.source_platform_object
@@ -83,7 +83,7 @@ class SlackEventConverter(adapter.EventConverter):
)
class SlackAdapter(adapter.MessagePlatformAdapter):
class SlackAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: SlackClient
bot_account_id: str
message_converter: SlackMessageConverter = SlackMessageConverter()
@@ -132,7 +132,9 @@ class SlackAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
async def on_message(event: SlackEvent):
self.bot_account_id = 'SlackBot'
@@ -163,6 +165,8 @@ class SlackAdapter(adapter.MessagePlatformAdapter):
async def unregister_listener(
self,
event_type: type,
callback: typing.Callable[[platform_events.Event, MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
return super().unregister_listener(event_type, callback)

View File

@@ -9,15 +9,16 @@ import typing
import traceback
import base64
import aiohttp
import pydantic
from .. import adapter
from ..types import message as platform_message
from ..types import events as platform_events
from ..types import entities as platform_entities
from ..logger import EventLogger
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.definition.abstract.platform.event_logger as abstract_platform_logger
class TelegramMessageConverter(adapter.MessageConverter):
class TelegramMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain, bot: telegram.Bot) -> list[dict]:
components = []
@@ -86,7 +87,7 @@ class TelegramMessageConverter(adapter.MessageConverter):
return platform_message.MessageChain(message_components)
class TelegramEventConverter(adapter.EventConverter):
class TelegramEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.MessageEvent, bot: telegram.Bot):
return event.source_platform_object
@@ -128,26 +129,19 @@ class TelegramEventConverter(adapter.EventConverter):
)
class TelegramAdapter(adapter.MessagePlatformAdapter):
bot: telegram.Bot
application: telegram.ext.Application
bot_account_id: str
class TelegramAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: telegram.Bot = pydantic.Field(exclude=True)
application: telegram.ext.Application = pydantic.Field(exclude=True)
message_converter: TelegramMessageConverter = TelegramMessageConverter()
event_converter: TelegramEventConverter = TelegramEventConverter()
config: dict
listeners: typing.Dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
] = {}
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.logger = logger
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger):
async def telegram_callback(update: Update, context: ContextTypes.DEFAULT_TYPE):
if update.message.from_user.is_bot:
return
@@ -158,10 +152,16 @@ class TelegramAdapter(adapter.MessagePlatformAdapter):
except Exception:
await self.logger.error(f'Error in telegram callback: {traceback.format_exc()}')
self.application = ApplicationBuilder().token(self.config['token']).build()
self.bot = self.application.bot
self.application.add_handler(
MessageHandler(filters.TEXT | (filters.COMMAND) | filters.PHOTO, telegram_callback)
application = ApplicationBuilder().token(config['token']).build()
bot = application.bot
application.add_handler(MessageHandler(filters.TEXT | (filters.COMMAND) | filters.PHOTO, telegram_callback))
super().__init__(
config=config,
logger=logger,
bot=bot,
application=application,
bot_account_id='',
listeners={},
)
async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain):
@@ -201,14 +201,18 @@ class TelegramAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners[event_type] = callback
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners.pop(event_type)

View File

@@ -3,17 +3,19 @@ import logging
import typing
from datetime import datetime
from pydantic import BaseModel
import pydantic
from .. import adapter as msadapter
from ..types import events as platform_events, message as platform_message, entities as platform_entities
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
from ...core import app
from ..logger import EventLogger
import langbot_plugin.api.definition.abstract.platform.event_logger as abstract_platform_logger
logger = logging.getLogger(__name__)
class WebChatMessage(BaseModel):
class WebChatMessage(pydantic.BaseModel):
id: int
role: str
content: str
@@ -38,28 +40,35 @@ class WebChatSession:
return self.message_lists[pipeline_uuid]
class WebChatAdapter(msadapter.MessagePlatformAdapter):
class WebChatAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
"""WebChat调试适配器用于流水线调试"""
webchat_person_session: WebChatSession
webchat_group_session: WebChatSession
webchat_person_session: WebChatSession = pydantic.Field(exclude=True, default_factory=WebChatSession)
webchat_group_session: WebChatSession = pydantic.Field(exclude=True, default_factory=WebChatSession)
ap: app.Application # set by bot manager
ap: app.Application = pydantic.Field(exclude=True) # set by bot manager
listeners: typing.Dict[
listeners: dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, msadapter.MessagePlatformAdapter], None],
] = {}
typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
] = pydantic.Field(default_factory=dict, exclude=True)
def __init__(self, config: dict, logger: EventLogger):
self.logger = logger
self.config = config
debug_messages: dict[str, list[dict]] = pydantic.Field(default_factory=dict, exclude=True)
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger, ap: app.Application):
super().__init__(
config=config,
logger=logger,
ap=ap,
)
self.webchat_person_session = WebChatSession(id='webchatperson')
self.webchat_group_session = WebChatSession(id='webchatgroup')
self.bot_account_id = 'webchatbot'
self.debug_messages = {}
async def send_message(
self,
target_type: str,
@@ -112,7 +121,9 @@ class WebChatAdapter(msadapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
func: typing.Callable[[platform_events.Event, msadapter.MessagePlatformAdapter], typing.Awaitable[None]],
func: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], typing.Awaitable[None]
],
):
"""注册事件监听器"""
self.listeners[event_type] = func
@@ -120,11 +131,16 @@ class WebChatAdapter(msadapter.MessagePlatformAdapter):
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
func: typing.Callable[[platform_events.Event, msadapter.MessagePlatformAdapter], typing.Awaitable[None]],
func: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], typing.Awaitable[None]
],
):
"""取消注册事件监听器"""
del self.listeners[event_type]
async def is_muted(self, group_id: int) -> bool:
return False
async def run_async(self):
"""运行适配器"""
await self.logger.info('WebChat调试适配器已启动')

View File

@@ -17,19 +17,19 @@ import threading
import quart
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 ..logger import EventLogger
import xml.etree.ElementTree as ET
from typing import Optional, Tuple
from functools import partial
import logging
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
class WeChatPadMessageConverter(adapter.MessageConverter):
class WeChatPadMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
def __init__(self, config: dict):
self.config = config
self.bot = WeChatPadClient(self.config['wechatpad_url'], self.config['token'])
@@ -281,7 +281,7 @@ class WeChatPadMessageConverter(adapter.MessageConverter):
"""处理文件消息 (data_type=6)"""
file_data = xml_data.find('.//appmsg')
if file_data.findtext('.//type', "") == "74":
if file_data.findtext('.//type', '') == '74':
return None
else:
@@ -304,16 +304,19 @@ class WeChatPadMessageConverter(adapter.MessageConverter):
file_data = self.bot.cdn_download(aeskey=aeskey, file_type=5, file_url=cdnthumburl)
file_base64 = file_data["Data"]['FileData']
file_base64 = file_data['Data']['FileData']
# print(file_data)
file_size = file_data["Data"]['TotalSize']
file_size = file_data['Data']['TotalSize']
# print(file_base64)
return platform_message.MessageChain([
platform_message.WeChatFile(file_id=file_id, file_name=file_name, file_size=file_size,
file_base64=file_base64),
platform_message.WeChatForwardFile(xml_data=xml_data_str)
])
return platform_message.MessageChain(
[
platform_message.WeChatFile(
file_id=file_id, file_name=file_name, file_size=file_size, file_base64=file_base64
),
platform_message.WeChatForwardFile(xml_data=xml_data_str),
]
)
async def _handler_compound_link(self, message: dict, xml_data: ET.Element) -> platform_message.MessageChain:
"""处理链接消息(如公众号文章、外部网页)"""
@@ -416,7 +419,7 @@ class WeChatPadMessageConverter(adapter.MessageConverter):
return from_user_name.endswith('@chatroom')
class WeChatPadEventConverter(adapter.EventConverter):
class WeChatPadEventConverter(abstract_platform_adapter.AbstractEventConverter):
def __init__(self, config: dict):
self.config = config
self.message_converter = WeChatPadMessageConverter(config)
@@ -476,7 +479,7 @@ class WeChatPadEventConverter(adapter.EventConverter):
)
class WeChatPadAdapter(adapter.MessagePlatformAdapter):
class WeChatPadAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
name: str = 'WeChatPad' # 定义适配器名称
bot: WeChatPadClient
@@ -495,7 +498,7 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
listeners: typing.Dict[
typing.Type[platform_events.Event],
typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
] = {}
def __init__(self, config: dict, ap: app.Application, logger: EventLogger):
@@ -596,14 +599,18 @@ class WeChatPadAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
self.listeners[event_type] = callback
def unregister_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
pass

View File

@@ -6,17 +6,17 @@ import traceback
import datetime
from libs.wecom_api.api import WecomClient
from pkg.platform.adapter import MessagePlatformAdapter
from pkg.platform.types import events as platform_events, message as platform_message
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
from libs.wecom_api.wecomevent import WecomEvent
from .. import adapter
from ..types import entities as platform_entities
from ...command.errors import ParamNotEnoughError
from ...utils import image
from ..logger import EventLogger
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
class WecomMessageConverter(adapter.MessageConverter):
class WecomMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain, bot: WecomClient):
content_list = []
@@ -70,7 +70,7 @@ class WecomMessageConverter(adapter.MessageConverter):
return chain
class WecomEventConverter:
class WecomEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.Event, bot_account_id: int, bot: WecomClient) -> WecomEvent:
# only for extracting user information
@@ -126,7 +126,7 @@ class WecomEventConverter:
return platform_events.FriendMessage(sender=friend, message_chain=yiri_chain, time=event.timestamp)
class WecomAdapter(adapter.MessagePlatformAdapter):
class WecomAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: WecomClient
bot_account_id: str
message_converter: WecomMessageConverter = WecomMessageConverter()
@@ -192,7 +192,9 @@ class WecomAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
async def on_message(event: WecomEvent):
self.bot_account_id = event.receiver_id
@@ -224,6 +226,8 @@ class WecomAdapter(adapter.MessagePlatformAdapter):
async def unregister_listener(
self,
event_type: type,
callback: typing.Callable[[platform_events.Event, MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
return super().unregister_listener(event_type, callback)

View File

@@ -4,18 +4,19 @@ import asyncio
import traceback
import datetime
import pydantic
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
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
from libs.wecom_customer_service_api.wecomcsevent import WecomCSEvent
from .. import adapter
from ..types import entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.entities as platform_entities
import langbot_plugin.api.entities.builtin.platform.message as platform_message
import langbot_plugin.api.entities.builtin.platform.events as platform_events
from ...command.errors import ParamNotEnoughError
from ..logger import EventLogger
import langbot_plugin.api.definition.abstract.platform.event_logger as abstract_platform_logger
class WecomMessageConverter(adapter.MessageConverter):
class WecomMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
async def yiri2target(message_chain: platform_message.MessageChain, bot: WecomCSClient):
content_list = []
@@ -68,7 +69,7 @@ class WecomMessageConverter(adapter.MessageConverter):
return chain
class WecomEventConverter:
class WecomEventConverter(abstract_platform_adapter.AbstractEventConverter):
@staticmethod
async def yiri2target(event: platform_events.Event, bot_account_id: int, bot: WecomCSClient) -> WecomCSEvent:
# only for extracting user information
@@ -116,17 +117,12 @@ class WecomEventConverter:
)
class WecomCSAdapter(adapter.MessagePlatformAdapter):
bot: WecomCSClient
bot_account_id: str
class WecomCSAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: WecomCSClient = pydantic.Field(exclude=True)
message_converter: WecomMessageConverter = WecomMessageConverter()
event_converter: WecomEventConverter = WecomEventConverter()
config: dict
def __init__(self, config: dict, logger: EventLogger):
self.config = config
self.logger = logger
def __init__(self, config: dict, logger: abstract_platform_logger.AbstractEventLogger):
required_keys = [
'corpid',
'secret',
@@ -137,12 +133,20 @@ class WecomCSAdapter(adapter.MessagePlatformAdapter):
if missing_keys:
raise ParamNotEnoughError('企业微信客服缺少相关配置项,请查看文档或联系管理员')
self.bot = WecomCSClient(
bot = WecomCSClient(
corpid=config['corpid'],
secret=config['secret'],
token=config['token'],
EncodingAESKey=config['EncodingAESKey'],
logger=self.logger,
logger=logger,
)
super().__init__(
config=config,
logger=logger,
bot=bot,
bot_account_id='',
listeners={},
)
async def reply_message(
@@ -169,7 +173,9 @@ class WecomCSAdapter(adapter.MessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
callback: typing.Callable[[platform_events.Event, adapter.MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
async def on_message(event: WecomCSEvent):
self.bot_account_id = event.receiver_id
@@ -198,9 +204,14 @@ class WecomCSAdapter(adapter.MessagePlatformAdapter):
async def kill(self) -> bool:
return False
async def is_muted(self, group_id: int) -> bool:
return False
async def unregister_listener(
self,
event_type: type,
callback: typing.Callable[[platform_events.Event, MessagePlatformAdapter], None],
callback: typing.Callable[
[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
],
):
return super().unregister_listener(event_type, callback)