mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-05 23:47:41 +08:00
Fix forwarded image payload parsing for agent channels
This commit is contained in:
@@ -193,10 +193,15 @@ class SlackModule(_ModuleBase, _MessageBase[Slack]):
|
|||||||
if not client_config:
|
if not client_config:
|
||||||
return None
|
return None
|
||||||
try:
|
try:
|
||||||
msg_json: dict = json.loads(body)
|
msg_json = json.loads(body)
|
||||||
|
while isinstance(msg_json, str):
|
||||||
|
msg_json = json.loads(msg_json)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.debug(f"解析Slack消息失败:{str(err)}")
|
logger.debug(f"解析Slack消息失败:{str(err)}")
|
||||||
return None
|
return None
|
||||||
|
if not isinstance(msg_json, dict):
|
||||||
|
logger.debug(f"Slack消息格式无效:{type(msg_json)}")
|
||||||
|
return None
|
||||||
if msg_json:
|
if msg_json:
|
||||||
images = None
|
images = None
|
||||||
if msg_json.get("type") == "message":
|
if msg_json.get("type") == "message":
|
||||||
|
|||||||
@@ -131,11 +131,21 @@ class TelegramModule(_ModuleBase, _MessageBase[Telegram]):
|
|||||||
return None
|
return None
|
||||||
client: Telegram = self.get_instance(client_config.name)
|
client: Telegram = self.get_instance(client_config.name)
|
||||||
try:
|
try:
|
||||||
message: dict = json.loads(body)
|
message = json.loads(body)
|
||||||
|
while isinstance(message, str):
|
||||||
|
message = json.loads(message)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
logger.debug(f"解析Telegram消息失败:{str(err)}")
|
logger.debug(f"解析Telegram消息失败:{str(err)}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if not isinstance(message, dict):
|
||||||
|
logger.debug(f"Telegram消息格式无效:{type(message)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 兼容某些转发链路使用 Telegram Update 外壳
|
||||||
|
if "message" in message and isinstance(message.get("message"), dict):
|
||||||
|
message = message.get("message")
|
||||||
|
|
||||||
if message:
|
if message:
|
||||||
# 处理按钮回调
|
# 处理按钮回调
|
||||||
if "callback_query" in message:
|
if "callback_query" in message:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
@@ -113,7 +114,11 @@ class Telegram:
|
|||||||
if self._should_process_message(message):
|
if self._should_process_message(message):
|
||||||
# 启动持续发送正在输入状态
|
# 启动持续发送正在输入状态
|
||||||
self._start_typing_task(message.chat.id)
|
self._start_typing_task(message.chat.id)
|
||||||
RequestUtils(timeout=15).post_res(self._ds_url, json=message.json)
|
payload = self._serialize_update_payload(message)
|
||||||
|
if not payload:
|
||||||
|
logger.warn("Telegram消息序列化失败,跳过转发")
|
||||||
|
return
|
||||||
|
RequestUtils(timeout=15).post_res(self._ds_url, json=payload)
|
||||||
|
|
||||||
@_bot.callback_query_handler(func=lambda call: True)
|
@_bot.callback_query_handler(func=lambda call: True)
|
||||||
def callback_query(call):
|
def callback_query(call):
|
||||||
@@ -208,6 +213,23 @@ class Telegram:
|
|||||||
logger.error(f"下载Telegram文件失败: {e}")
|
logger.error(f"下载Telegram文件失败: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _serialize_update_payload(message: Any) -> Optional[dict]:
|
||||||
|
"""
|
||||||
|
将 Telegram Message 对象稳定序列化为 dict,避免 requests 的 json 参数再次包一层字符串。
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if hasattr(message, "to_dict"):
|
||||||
|
payload = message.to_dict()
|
||||||
|
else:
|
||||||
|
payload = getattr(message, "json", None) or message
|
||||||
|
if isinstance(payload, str):
|
||||||
|
payload = json.loads(payload)
|
||||||
|
return payload if isinstance(payload, dict) else None
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"序列化Telegram消息失败: {e}")
|
||||||
|
return None
|
||||||
|
|
||||||
def _update_user_chat_mapping(self, userid: int, chat_id: int) -> None:
|
def _update_user_chat_mapping(self, userid: int, chat_id: int) -> None:
|
||||||
"""
|
"""
|
||||||
更新用户与聊天的映射关系
|
更新用户与聊天的映射关系
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import base64
|
import base64
|
||||||
|
import json
|
||||||
import unittest
|
import unittest
|
||||||
from types import SimpleNamespace
|
from types import SimpleNamespace
|
||||||
from unittest.mock import Mock, patch
|
from unittest.mock import Mock, patch
|
||||||
@@ -7,6 +8,7 @@ from app.agent.tools.impl.send_message import SendMessageInput
|
|||||||
from app.chain.message import MessageChain
|
from app.chain.message import MessageChain
|
||||||
from app.core.config import settings
|
from app.core.config import settings
|
||||||
from app.modules.slack import SlackModule
|
from app.modules.slack import SlackModule
|
||||||
|
from app.modules.telegram.telegram import Telegram
|
||||||
from app.modules.telegram import TelegramModule
|
from app.modules.telegram import TelegramModule
|
||||||
from app.schemas import CommingMessage
|
from app.schemas import CommingMessage
|
||||||
from app.schemas.types import MessageChannel
|
from app.schemas.types import MessageChannel
|
||||||
@@ -26,6 +28,51 @@ class AgentImageSupportTest(unittest.TestCase):
|
|||||||
["tg://file_id/large", "tg://file_id/doc-image"],
|
["tg://file_id/large", "tg://file_id/doc-image"],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_telegram_message_parser_accepts_double_encoded_body(self):
|
||||||
|
module = TelegramModule()
|
||||||
|
body = json.dumps(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"message": {
|
||||||
|
"from": {"id": 10001, "username": "tester"},
|
||||||
|
"chat": {"id": 10001, "type": "private"},
|
||||||
|
"photo": [{"file_id": "small"}, {"file_id": "large"}],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
with patch.object(
|
||||||
|
module,
|
||||||
|
"get_config",
|
||||||
|
return_value=SimpleNamespace(name="telegram-test", config={}),
|
||||||
|
), patch.object(
|
||||||
|
module,
|
||||||
|
"get_instance",
|
||||||
|
return_value=SimpleNamespace(bot_username=None),
|
||||||
|
):
|
||||||
|
message = module.message_parser(
|
||||||
|
source="telegram-test", body=body, form={}, args={}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertIsNotNone(message)
|
||||||
|
self.assertEqual(message.images, ["tg://file_id/large"])
|
||||||
|
|
||||||
|
def test_telegram_forward_payload_uses_dict_not_json_string(self):
|
||||||
|
payload = Telegram._serialize_update_payload(
|
||||||
|
SimpleNamespace(
|
||||||
|
to_dict=lambda: {
|
||||||
|
"text": "hi",
|
||||||
|
"photo": [{"file_id": "image-1"}],
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
payload,
|
||||||
|
{"text": "hi", "photo": [{"file_id": "image-1"}]},
|
||||||
|
)
|
||||||
|
|
||||||
def test_process_allows_image_only_message(self):
|
def test_process_allows_image_only_message(self):
|
||||||
chain = MessageChain()
|
chain = MessageChain()
|
||||||
message = CommingMessage(
|
message = CommingMessage(
|
||||||
|
|||||||
Reference in New Issue
Block a user