diff --git a/src/langbot/libs/wecom_ai_bot_api/api.py b/src/langbot/libs/wecom_ai_bot_api/api.py
index 2ac01b89..bed94d02 100644
--- a/src/langbot/libs/wecom_ai_bot_api/api.py
+++ b/src/langbot/libs/wecom_ai_bot_api/api.py
@@ -13,9 +13,9 @@ import httpx
from Crypto.Cipher import AES
from quart import Quart, request, Response, jsonify
-from libs.wecom_ai_bot_api import wecombotevent
-from libs.wecom_ai_bot_api.WXBizMsgCrypt3 import WXBizMsgCrypt
-from pkg.platform.logger import EventLogger
+from langbot.libs.wecom_ai_bot_api import wecombotevent
+from langbot.libs.wecom_ai_bot_api.WXBizMsgCrypt3 import WXBizMsgCrypt
+from langbot.pkg.platform.logger import EventLogger
@dataclass
@@ -224,10 +224,7 @@ class WecomBotClient:
# 只有在非统一模式下才注册独立路由
if not self.unified_mode:
self.app.add_url_rule(
- '/callback/command',
- 'handle_callback',
- self.handle_callback_request,
- methods=['POST', 'GET']
+ '/callback/command', 'handle_callback', self.handle_callback_request, methods=['POST', 'GET']
)
self._message_handlers = {
@@ -445,7 +442,7 @@ class WecomBotClient:
await self.logger.error("请求体中缺少 'encrypt' 字段")
return Response('Bad Request', status=400)
- xml_post_data = f""
+ xml_post_data = f''
ret, decrypted_xml = self.wxcpt.DecryptMsg(xml_post_data, msg_signature, timestamp, nonce)
if ret != 0:
await self.logger.error('解密失败')
@@ -483,7 +480,7 @@ class WecomBotClient:
picurl = item.get('image', {}).get('url')
if texts:
- message_data['content'] = "".join(texts) # 拼接所有 text
+ message_data['content'] = ''.join(texts) # 拼接所有 text
if picurl:
base64 = await self.download_url_to_base64(picurl, self.EnCodingAESKey)
message_data['picurl'] = base64 # 只保留第一个 image
@@ -491,7 +488,9 @@ class WecomBotClient:
# Extract user information
from_info = msg_json.get('from', {})
message_data['userid'] = from_info.get('userid', '')
- message_data['username'] = from_info.get('alias', '') or from_info.get('name', '') or from_info.get('userid', '')
+ message_data['username'] = (
+ from_info.get('alias', '') or from_info.get('name', '') or from_info.get('userid', '')
+ )
# Extract chat/group information
if msg_json.get('chattype', '') == 'group':
@@ -580,7 +579,7 @@ class WecomBotClient:
encrypted_bytes = response.content
- aes_key = base64.b64decode(encoding_aes_key + "=") # base64 补齐
+ aes_key = base64.b64decode(encoding_aes_key + '=') # base64 补齐
iv = aes_key[:16]
cipher = AES.new(aes_key, AES.MODE_CBC, iv)
@@ -589,22 +588,22 @@ class WecomBotClient:
pad_len = decrypted[-1]
decrypted = decrypted[:-pad_len]
- if decrypted.startswith(b"\xff\xd8"): # JPEG
- mime_type = "image/jpeg"
- elif decrypted.startswith(b"\x89PNG"): # PNG
- mime_type = "image/png"
- elif decrypted.startswith((b"GIF87a", b"GIF89a")): # GIF
- mime_type = "image/gif"
- elif decrypted.startswith(b"BM"): # BMP
- mime_type = "image/bmp"
- elif decrypted.startswith(b"II*\x00") or decrypted.startswith(b"MM\x00*"): # TIFF
- mime_type = "image/tiff"
+ if decrypted.startswith(b'\xff\xd8'): # JPEG
+ mime_type = 'image/jpeg'
+ elif decrypted.startswith(b'\x89PNG'): # PNG
+ mime_type = 'image/png'
+ elif decrypted.startswith((b'GIF87a', b'GIF89a')): # GIF
+ mime_type = 'image/gif'
+ elif decrypted.startswith(b'BM'): # BMP
+ mime_type = 'image/bmp'
+ elif decrypted.startswith(b'II*\x00') or decrypted.startswith(b'MM\x00*'): # TIFF
+ mime_type = 'image/tiff'
else:
- mime_type = "application/octet-stream"
+ mime_type = 'application/octet-stream'
# 转 base64
- base64_str = base64.b64encode(decrypted).decode("utf-8")
- return f"data:{mime_type};base64,{base64_str}"
+ base64_str = base64.b64encode(decrypted).decode('utf-8')
+ return f'data:{mime_type};base64,{base64_str}'
async def run_task(self, host: str, port: int, *args, **kwargs):
"""
diff --git a/src/langbot/pkg/api/http/service/bot.py b/src/langbot/pkg/api/http/service/bot.py
index f171e35d..2942521c 100644
--- a/src/langbot/pkg/api/http/service/bot.py
+++ b/src/langbot/pkg/api/http/service/bot.py
@@ -58,11 +58,11 @@ class BotService:
if runtime_bot is not None:
adapter_runtime_values['bot_account_id'] = runtime_bot.adapter.bot_account_id
- if persistence_bot['adapter'] in ['wecom', 'wecombot', 'officialaccount', 'qqofficial', 'slack','wecomcs']:
+ if persistence_bot['adapter'] in ['wecom', 'wecombot', 'officialaccount', 'qqofficial', 'slack', 'wecomcs']:
api_port = self.ap.instance_config.data['api']['port']
- webhook_url = f"/bots/{bot_uuid}"
+ webhook_url = f'/bots/{bot_uuid}'
adapter_runtime_values['webhook_url'] = webhook_url
- adapter_runtime_values['webhook_full_url'] = f"http://:{api_port}{webhook_url}"
+ adapter_runtime_values['webhook_full_url'] = f'http://:{api_port}{webhook_url}'
else:
adapter_runtime_values['webhook_url'] = None
adapter_runtime_values['webhook_full_url'] = None
diff --git a/src/langbot/pkg/platform/sources/officialaccount.py b/src/langbot/pkg/platform/sources/officialaccount.py
index 3d339fa0..5f6f0e41 100644
--- a/src/langbot/pkg/platform/sources/officialaccount.py
+++ b/src/langbot/pkg/platform/sources/officialaccount.py
@@ -5,13 +5,12 @@ import traceback
import pydantic
import datetime
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 langbot.libs.official_account_api.oaevent import OAEvent
+from langbot.libs.official_account_api.api import OAClient
+from langbot.libs.official_account_api.api import OAClientForLongerResponse
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 langbot_plugin.api.entities.builtin.command import errors as command_errors
from ..logger import EventLogger
@@ -93,7 +92,6 @@ class OfficialAccountAdapter(abstract_platform_adapter.AbstractMessagePlatformAd
bot_account_id = config.get('AppID', '')
-
super().__init__(
bot=bot,
bot_account_id=bot_account_id,
@@ -101,10 +99,6 @@ class OfficialAccountAdapter(abstract_platform_adapter.AbstractMessagePlatformAd
logger=logger,
)
-
-
-
-
async def reply_message(
self,
message_source: platform_events.FriendMessage,
@@ -165,19 +159,20 @@ class OfficialAccountAdapter(abstract_platform_adapter.AbstractMessagePlatformAd
if self.bot_uuid and hasattr(self.logger, 'ap'):
try:
api_port = self.logger.ap.instance_config.data['api']['port']
- webhook_url = f"http://127.0.0.1:{api_port}/bots/{self.bot_uuid}"
- webhook_url_public = f"http://:{api_port}/bots/{self.bot_uuid}"
+ webhook_url = f'http://127.0.0.1:{api_port}/bots/{self.bot_uuid}'
+ webhook_url_public = f'http://:{api_port}/bots/{self.bot_uuid}'
- await self.logger.info(f"微信公众号 Webhook 回调地址:")
- await self.logger.info(f" 本地地址: {webhook_url}")
- await self.logger.info(f" 公网地址: {webhook_url_public}")
- await self.logger.info(f"请在微信公众号后台配置此回调地址")
+ await self.logger.info('微信公众号 Webhook 回调地址:')
+ await self.logger.info(f' 本地地址: {webhook_url}')
+ await self.logger.info(f' 公网地址: {webhook_url_public}')
+ await self.logger.info('请在微信公众号后台配置此回调地址')
except Exception as e:
- await self.logger.warning(f"无法生成 webhook URL: {e}")
+ await self.logger.warning(f'无法生成 webhook URL: {e}')
async def keep_alive():
while True:
await asyncio.sleep(1)
+
await keep_alive()
async def kill(self) -> bool:
@@ -192,5 +187,8 @@ class OfficialAccountAdapter(abstract_platform_adapter.AbstractMessagePlatformAd
):
return super().unregister_listener(event_type, callback)
- async def is_muted(self, group_id: str, ) -> bool:
+ async def is_muted(
+ self,
+ group_id: str,
+ ) -> bool:
pass
diff --git a/src/langbot/pkg/platform/sources/qqofficial.py b/src/langbot/pkg/platform/sources/qqofficial.py
index 91989126..a3288793 100644
--- a/src/langbot/pkg/platform/sources/qqofficial.py
+++ b/src/langbot/pkg/platform/sources/qqofficial.py
@@ -9,9 +9,8 @@ import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platf
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 langbot_plugin.api.entities.builtin.command import errors as command_errors
-from libs.qq_official_api.api import QQOfficialClient
-from libs.qq_official_api.qqofficialevent import QQOfficialEvent
+from langbot.libs.qq_official_api.api import QQOfficialClient
+from langbot.libs.qq_official_api.qqofficialevent import QQOfficialEvent
from ...utils import image
from ..logger import EventLogger
@@ -141,11 +140,7 @@ class QQOfficialAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter
def __init__(self, config: dict, logger: EventLogger):
bot = QQOfficialClient(
- app_id=config['appid'],
- secret=config['secret'],
- token=config['token'],
- logger=logger,
- unified_mode=True
+ app_id=config['appid'], secret=config['secret'], token=config['token'], logger=logger, unified_mode=True
)
super().__init__(
@@ -256,19 +251,20 @@ class QQOfficialAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter
if self.bot_uuid and hasattr(self.logger, 'ap'):
try:
api_port = self.logger.ap.instance_config.data['api']['port']
- webhook_url = f"http://127.0.0.1:{api_port}/bots/{self.bot_uuid}"
- webhook_url_public = f"http://:{api_port}/bots/{self.bot_uuid}"
+ webhook_url = f'http://127.0.0.1:{api_port}/bots/{self.bot_uuid}'
+ webhook_url_public = f'http://:{api_port}/bots/{self.bot_uuid}'
- await self.logger.info(f"QQ 官方机器人 Webhook 回调地址:")
- await self.logger.info(f" 本地地址: {webhook_url}")
- await self.logger.info(f" 公网地址: {webhook_url_public}")
- await self.logger.info(f"请在 QQ 官方机器人后台配置此回调地址")
+ await self.logger.info('QQ 官方机器人 Webhook 回调地址:')
+ await self.logger.info(f' 本地地址: {webhook_url}')
+ await self.logger.info(f' 公网地址: {webhook_url_public}')
+ await self.logger.info('请在 QQ 官方机器人后台配置此回调地址')
except Exception as e:
- await self.logger.warning(f"无法生成 webhook URL: {e}")
+ await self.logger.warning(f'无法生成 webhook URL: {e}')
async def keep_alive():
while True:
await asyncio.sleep(1)
+
await keep_alive()
async def kill(self) -> bool:
diff --git a/src/langbot/pkg/platform/sources/wecom.py b/src/langbot/pkg/platform/sources/wecom.py
index 1bf2108d..21daad67 100644
--- a/src/langbot/pkg/platform/sources/wecom.py
+++ b/src/langbot/pkg/platform/sources/wecom.py
@@ -5,10 +5,9 @@ import traceback
import datetime
-from libs.wecom_api.api import WecomClient
+from langbot.libs.wecom_api.api import WecomClient
import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platform_adapter
-from libs.wecom_api.wecomevent import WecomEvent
-from langbot_plugin.api.entities.builtin.command import errors as command_errors
+from langbot.libs.wecom_api.wecomevent import WecomEvent
from ...utils import image
from ..logger import EventLogger
import langbot_plugin.api.entities.builtin.platform.message as platform_message
@@ -159,12 +158,11 @@ class WecomAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
unified_mode=True,
)
-
super().__init__(
config=config,
logger=logger,
bot=bot,
- bot_account_id="",
+ bot_account_id='',
)
def set_bot_uuid(self, bot_uuid: str):
@@ -189,7 +187,6 @@ class WecomAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
await self.bot.send_image(fixed_user_id, Wecom_event.agent_id, content['media_id'])
async def send_message(self, target_type: str, target_id: str, message: platform_message.MessageChain):
-
content_list = await WecomMessageConverter.yiri2target(message, self.bot)
parts = target_id.split('|')
user_id = parts[0]
@@ -235,23 +232,23 @@ class WecomAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
return await self.bot.handle_unified_webhook(request)
async def run_async(self):
-
if self.bot_uuid and hasattr(self.logger, 'ap'):
try:
api_port = self.logger.ap.instance_config.data['api']['port']
- webhook_url = f"http://127.0.0.1:{api_port}/bots/{self.bot_uuid}"
- webhook_url_public = f"http://:{api_port}/bots/{self.bot_uuid}"
+ webhook_url = f'http://127.0.0.1:{api_port}/bots/{self.bot_uuid}'
+ webhook_url_public = f'http://:{api_port}/bots/{self.bot_uuid}'
- await self.logger.info(f"企业微信 Webhook 回调地址:")
- await self.logger.info(f" 本地地址: {webhook_url}")
- await self.logger.info(f" 公网地址: {webhook_url_public}")
- await self.logger.info(f"请在企业微信后台配置此回调地址")
+ await self.logger.info('企业微信 Webhook 回调地址:')
+ await self.logger.info(f' 本地地址: {webhook_url}')
+ await self.logger.info(f' 公网地址: {webhook_url_public}')
+ await self.logger.info('请在企业微信后台配置此回调地址')
except Exception as e:
- await self.logger.warning(f"无法生成 webhook URL: {e}")
+ await self.logger.warning(f'无法生成 webhook URL: {e}')
async def keep_alive():
while True:
await asyncio.sleep(1)
+
await keep_alive()
async def kill(self) -> bool:
@@ -265,6 +262,6 @@ class WecomAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
],
):
return super().unregister_listener(event_type, callback)
-
+
async def is_muted(self, group_id: int) -> bool:
pass
diff --git a/src/langbot/pkg/platform/sources/wecombot.py b/src/langbot/pkg/platform/sources/wecombot.py
index d2d363f9..5fd66aca 100644
--- a/src/langbot/pkg/platform/sources/wecombot.py
+++ b/src/langbot/pkg/platform/sources/wecombot.py
@@ -8,11 +8,10 @@ import langbot_plugin.api.definition.abstract.platform.adapter as abstract_platf
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 pydantic
-from ..logger import EventLogger
-from libs.wecom_ai_bot_api.wecombotevent import WecomBotEvent
-from libs.wecom_ai_bot_api.api import WecomBotClient
-from ...core import app
+from ..logger import EventLogger
+from langbot.libs.wecom_ai_bot_api.wecombotevent import WecomBotEvent
+from langbot.libs.wecom_ai_bot_api.api import WecomBotClient
+
class WecomBotMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
@staticmethod
@@ -36,14 +35,14 @@ class WecomBotMessageConverter(abstract_platform_adapter.AbstractMessageConverte
return chain
+
class WecomBotEventConverter(abstract_platform_adapter.AbstractEventConverter):
+ @staticmethod
+ async def yiri2target(event: platform_events.MessageEvent):
+ return event.source_platform_object
@staticmethod
- async def yiri2target(event:platform_events.MessageEvent):
- return event.source_platform_object
-
- @staticmethod
- async def target2yiri(event:WecomBotEvent):
+ async def target2yiri(event: WecomBotEvent):
message_chain = await WecomBotMessageConverter.target2yiri(event)
if event.type == 'single':
return platform_events.FriendMessage(
@@ -82,6 +81,7 @@ class WecomBotEventConverter(abstract_platform_adapter.AbstractEventConverter):
except Exception:
print(traceback.format_exc())
+
class WecomBotAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot: WecomBotClient
bot_account_id: str
@@ -91,13 +91,11 @@ class WecomBotAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot_uuid: str = None
def __init__(self, config: dict, logger: EventLogger):
-
required_keys = ['Token', 'EncodingAESKey', 'Corpid', 'BotId']
missing_keys = [key for key in required_keys if key not in config]
if missing_keys:
raise Exception(f'WecomBot 缺少配置项: {missing_keys}')
-
bot = WecomBotClient(
Token=config['Token'],
EnCodingAESKey=config['EncodingAESKey'],
@@ -114,9 +112,12 @@ class WecomBotAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
bot_account_id=bot_account_id,
)
-
- async def reply_message(self, message_source:platform_events.MessageEvent, message:platform_message.MessageChain,quote_origin: bool = False):
-
+ async def reply_message(
+ self,
+ message_source: platform_events.MessageEvent,
+ message: platform_message.MessageChain,
+ quote_origin: bool = False,
+ ):
content = await self.message_converter.yiri2target(message)
await self.bot.set_message(message_source.source_platform_object.message_id, content)
@@ -170,7 +171,9 @@ class WecomBotAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
def register_listener(
self,
event_type: typing.Type[platform_events.Event],
- callback: typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
+ callback: typing.Callable[
+ [platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
+ ],
):
async def on_message(event: WecomBotEvent):
try:
@@ -178,6 +181,7 @@ class WecomBotAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
except Exception:
await self.logger.error(f'Error in wecombot callback: {traceback.format_exc()}')
print(traceback.format_exc())
+
try:
if event_type == platform_events.FriendMessage:
self.bot.on_message('single')(on_message)
@@ -211,19 +215,20 @@ class WecomBotAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
if self.bot_uuid and hasattr(self.logger, 'ap'):
try:
api_port = self.logger.ap.instance_config.data['api']['port']
- webhook_url = f"http://127.0.0.1:{api_port}/bots/{self.bot_uuid}"
- webhook_url_public = f"http://:{api_port}/bots/{self.bot_uuid}"
+ webhook_url = f'http://127.0.0.1:{api_port}/bots/{self.bot_uuid}'
+ webhook_url_public = f'http://:{api_port}/bots/{self.bot_uuid}'
- await self.logger.info(f"企业微信机器人 Webhook 回调地址:")
- await self.logger.info(f" 本地地址: {webhook_url}")
- await self.logger.info(f" 公网地址: {webhook_url_public}")
- await self.logger.info(f"请在企业微信后台配置此回调地址")
+ await self.logger.info('企业微信机器人 Webhook 回调地址:')
+ await self.logger.info(f' 本地地址: {webhook_url}')
+ await self.logger.info(f' 公网地址: {webhook_url_public}')
+ await self.logger.info('请在企业微信后台配置此回调地址')
except Exception as e:
- await self.logger.warning(f"无法生成 webhook URL: {e}")
+ await self.logger.warning(f'无法生成 webhook URL: {e}')
async def keep_alive():
while True:
await asyncio.sleep(1)
+
await keep_alive()
async def kill(self) -> bool:
@@ -232,11 +237,11 @@ class WecomBotAdapter(abstract_platform_adapter.AbstractMessagePlatformAdapter):
async def unregister_listener(
self,
event_type: type,
- callback: typing.Callable[[platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None],
+ callback: typing.Callable[
+ [platform_events.Event, abstract_platform_adapter.AbstractMessagePlatformAdapter], None
+ ],
):
return super().unregister_listener(event_type, callback)
-
+
async def is_muted(self, group_id: int) -> bool:
pass
-
-