mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-08-04 04:37:18 +08:00
feat(feishu): enhance message handling with file and voice support, add reaction management
This commit is contained in:
@@ -5,6 +5,7 @@ import mimetypes
|
||||
import re
|
||||
import time
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Any, Optional, Dict, Union, List, Tuple
|
||||
@@ -47,6 +48,13 @@ class MessageChain(ChainBase):
|
||||
# 会话超时时间(分钟)
|
||||
_session_timeout_minutes: int = 24 * 60
|
||||
|
||||
@dataclass
|
||||
class _ProcessingMarker:
|
||||
channel: MessageChannel
|
||||
source: str
|
||||
message_id: str
|
||||
reaction_id: str
|
||||
|
||||
def process(self, body: Any, form: Any, args: Any) -> None:
|
||||
"""
|
||||
调用模块识别消息内容
|
||||
@@ -151,6 +159,46 @@ class MessageChain(ChainBase):
|
||||
text=text,
|
||||
)
|
||||
|
||||
processing_marker = self._mark_message_processing_started(
|
||||
channel=channel,
|
||||
source=source,
|
||||
original_message_id=original_message_id,
|
||||
text=text,
|
||||
)
|
||||
|
||||
try:
|
||||
self._handle_message_core(
|
||||
channel=channel,
|
||||
source=source,
|
||||
userid=userid,
|
||||
username=username,
|
||||
text=text,
|
||||
original_message_id=original_message_id,
|
||||
original_chat_id=original_chat_id,
|
||||
images=images,
|
||||
audio_refs=audio_refs,
|
||||
files=files,
|
||||
has_audio_input=has_audio_input,
|
||||
)
|
||||
finally:
|
||||
self._mark_message_processing_finished(processing_marker)
|
||||
|
||||
def _handle_message_core(
|
||||
self,
|
||||
channel: MessageChannel,
|
||||
source: str,
|
||||
userid: Union[str, int],
|
||||
username: str,
|
||||
text: str,
|
||||
original_message_id: Optional[Union[str, int]] = None,
|
||||
original_chat_id: Optional[str] = None,
|
||||
images: Optional[List[CommingMessage.MessageImage]] = None,
|
||||
audio_refs: Optional[List[str]] = None,
|
||||
files: Optional[List[CommingMessage.MessageAttachment]] = None,
|
||||
has_audio_input: bool = False,
|
||||
) -> None:
|
||||
"""执行实际消息路由,便于统一包裹处理中状态。"""
|
||||
|
||||
if text.startswith("CALLBACK:"):
|
||||
if ChannelCapabilityManager.supports_callbacks(channel):
|
||||
self._handle_callback(
|
||||
@@ -264,6 +312,49 @@ class MessageChain(ChainBase):
|
||||
},
|
||||
)
|
||||
|
||||
def _mark_message_processing_started(
|
||||
self,
|
||||
channel: MessageChannel,
|
||||
source: str,
|
||||
original_message_id: Optional[Union[str, int]],
|
||||
text: str,
|
||||
) -> Optional[_ProcessingMarker]:
|
||||
"""为支持的渠道标记“消息正在处理”。"""
|
||||
if channel != MessageChannel.Feishu:
|
||||
return None
|
||||
if not original_message_id or not text or text.startswith("CALLBACK:"):
|
||||
return None
|
||||
|
||||
reaction_id = self.run_module(
|
||||
"add_feishu_message_reaction",
|
||||
message_id=str(original_message_id),
|
||||
emoji_type="GLANCE",
|
||||
source=source,
|
||||
)
|
||||
if not reaction_id:
|
||||
return None
|
||||
|
||||
return self._ProcessingMarker(
|
||||
channel=channel,
|
||||
source=source,
|
||||
message_id=str(original_message_id),
|
||||
reaction_id=str(reaction_id),
|
||||
)
|
||||
|
||||
def _mark_message_processing_finished(
|
||||
self,
|
||||
marker: Optional[_ProcessingMarker],
|
||||
) -> None:
|
||||
"""清理渠道“消息正在处理”标记。"""
|
||||
if not marker:
|
||||
return
|
||||
self.run_module(
|
||||
"delete_feishu_message_reaction",
|
||||
message_id=marker.message_id,
|
||||
reaction_id=marker.reaction_id,
|
||||
source=marker.source,
|
||||
)
|
||||
|
||||
def _handle_callback(
|
||||
self,
|
||||
text: str,
|
||||
@@ -1098,12 +1189,14 @@ class MessageChain(ChainBase):
|
||||
),
|
||||
global_vars.loop,
|
||||
)
|
||||
return
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"处理AI智能体消息失败: {e}")
|
||||
self.messagehelper.put(
|
||||
f"AI智能体处理失败: {str(e)}", role="system", title="MoviePilot助手"
|
||||
)
|
||||
return
|
||||
|
||||
def _transcribe_audio_refs(
|
||||
self, audio_refs: List[str], channel: MessageChannel, source: str
|
||||
@@ -1289,6 +1382,14 @@ class MessageChain(ChainBase):
|
||||
)
|
||||
if data_url:
|
||||
data_urls.append(data_url)
|
||||
elif attachment_ref.startswith("feishu://image/"):
|
||||
data_url = self.run_module(
|
||||
"download_feishu_image_to_data_url",
|
||||
image_ref=attachment_ref,
|
||||
source=source,
|
||||
)
|
||||
if data_url:
|
||||
data_urls.append(data_url)
|
||||
elif channel == MessageChannel.Slack:
|
||||
data_url = self.run_module(
|
||||
"download_slack_file_to_data_url",
|
||||
@@ -1462,6 +1563,10 @@ class MessageChain(ChainBase):
|
||||
return self.run_module(
|
||||
"download_wechat_media_bytes", media_ref=file_ref, source=source
|
||||
)
|
||||
if file_ref.startswith("feishu://file/"):
|
||||
return self.run_module(
|
||||
"download_feishu_file_bytes", file_ref=file_ref, source=source
|
||||
)
|
||||
if file_ref.startswith("slack://file/"):
|
||||
return self.run_module(
|
||||
"download_slack_file_bytes", file_ref=file_ref, source=source
|
||||
|
||||
Reference in New Issue
Block a user