fix: 飞书机器人群聊回复逻辑
This commit is contained in:
76
fsapp.py
76
fsapp.py
@@ -245,15 +245,15 @@ def _card(text):
|
||||
return json.dumps({"config": {"wide_screen_mode": True}, "elements": [{"tag": "markdown", "content": text}]}, ensure_ascii=False)
|
||||
|
||||
|
||||
def send_message(open_id, content, msg_type="text", use_card=False):
|
||||
def send_message(receive_id, content, msg_type="text", use_card=False, receive_id_type="open_id"):
|
||||
if use_card:
|
||||
payload, real_type = _card(content), "interactive"
|
||||
elif msg_type == "text":
|
||||
payload, real_type = json.dumps({"text": content}, ensure_ascii=False), "text"
|
||||
else:
|
||||
payload, real_type = content, msg_type
|
||||
body = CreateMessageRequest.builder().receive_id_type("open_id").request_body(
|
||||
CreateMessageRequestBody.builder().receive_id(open_id).msg_type(real_type).content(payload).build()
|
||||
body = CreateMessageRequest.builder().receive_id_type(receive_id_type).request_body(
|
||||
CreateMessageRequestBody.builder().receive_id(receive_id).msg_type(real_type).content(payload).build()
|
||||
).build()
|
||||
response = client.im.v1.message.create(body)
|
||||
if response.success():
|
||||
@@ -367,29 +367,29 @@ def _describe_media(msg_type, file_path, filename):
|
||||
return f"[{msg_type}]\n[File: source: {file_path}]"
|
||||
|
||||
|
||||
def _send_local_file(open_id, file_path):
|
||||
def _send_local_file(receive_id, file_path, receive_id_type="open_id"):
|
||||
if not os.path.isfile(file_path):
|
||||
send_message(open_id, f"⚠️ 文件不存在: {file_path}")
|
||||
send_message(receive_id, f"⚠️ 文件不存在: {file_path}", receive_id_type=receive_id_type)
|
||||
return False
|
||||
ext = os.path.splitext(file_path)[1].lower()
|
||||
if ext in _IMAGE_EXTS:
|
||||
image_key = _upload_image_sync(file_path)
|
||||
if image_key:
|
||||
send_message(open_id, json.dumps({"image_key": image_key}, ensure_ascii=False), msg_type="image")
|
||||
send_message(receive_id, json.dumps({"image_key": image_key}, ensure_ascii=False), msg_type="image", receive_id_type=receive_id_type)
|
||||
return True
|
||||
else:
|
||||
file_key = _upload_file_sync(file_path)
|
||||
if file_key:
|
||||
msg_type = "media" if ext in _AUDIO_EXTS or ext in _VIDEO_EXTS else "file"
|
||||
send_message(open_id, json.dumps({"file_key": file_key}, ensure_ascii=False), msg_type=msg_type)
|
||||
send_message(receive_id, json.dumps({"file_key": file_key}, ensure_ascii=False), msg_type=msg_type, receive_id_type=receive_id_type)
|
||||
return True
|
||||
send_message(open_id, f"⚠️ 文件发送失败: {os.path.basename(file_path)}")
|
||||
send_message(receive_id, f"⚠️ 文件发送失败: {os.path.basename(file_path)}", receive_id_type=receive_id_type)
|
||||
return False
|
||||
|
||||
|
||||
def _send_generated_files(open_id, raw_text):
|
||||
def _send_generated_files(receive_id, raw_text, receive_id_type="open_id"):
|
||||
for file_path in _extract_files(raw_text):
|
||||
_send_local_file(open_id, file_path)
|
||||
_send_local_file(receive_id, file_path, receive_id_type)
|
||||
|
||||
|
||||
def _build_user_message(message):
|
||||
@@ -430,21 +430,28 @@ def _build_user_message(message):
|
||||
def handle_message(data):
|
||||
event, message, sender = data.event, data.event.message, data.event.sender
|
||||
open_id = sender.sender_id.open_id
|
||||
chat_id = message.chat_id
|
||||
if not PUBLIC_ACCESS and open_id not in ALLOWED_USERS:
|
||||
print(f"未授权用户: {open_id}")
|
||||
return
|
||||
user_input, image_paths = _build_user_message(message)
|
||||
if not user_input:
|
||||
send_message(open_id, f"⚠️ 暂不支持处理此类飞书消息:{message.message_type}")
|
||||
if chat_id:
|
||||
send_message(chat_id, f"⚠️ 暂不支持处理此类飞书消息:{message.message_type}", receive_id_type="chat_id")
|
||||
else:
|
||||
send_message(open_id, f"⚠️ 暂不支持处理此类飞书消息:{message.message_type}")
|
||||
return
|
||||
print(f"收到消息 [{open_id}] ({message.message_type}, {len(image_paths)} images): {user_input[:200]}")
|
||||
if message.message_type == "text" and user_input.startswith("/"):
|
||||
return handle_command(open_id, user_input)
|
||||
return handle_command(open_id, user_input, chat_id)
|
||||
|
||||
def run_agent():
|
||||
user_tasks[open_id] = {"running": True}
|
||||
try:
|
||||
msg_id, dq, last_text = send_message(open_id, "思考中...", use_card=True), agent.put_task(user_input, source="feishu", images=image_paths), ""
|
||||
if chat_id:
|
||||
msg_id, dq, last_text = send_message(chat_id, "思考中...", use_card=True, receive_id_type="chat_id"), agent.put_task(user_input, source="feishu", images=image_paths), ""
|
||||
else:
|
||||
msg_id, dq, last_text = send_message(open_id, "思考中...", use_card=True), agent.put_task(user_input, source="feishu", images=image_paths), ""
|
||||
while user_tasks.get(open_id, {}).get("running", False):
|
||||
time.sleep(3)
|
||||
item = None
|
||||
@@ -462,47 +469,64 @@ def handle_message(data):
|
||||
cut = show[-3000:]
|
||||
if cut.count("```") % 2 == 1:
|
||||
cut = "```\n" + cut
|
||||
msg_id, last_text, show = send_message(open_id, "(继续...)", use_card=True), "", cut
|
||||
if chat_id:
|
||||
msg_id, last_text, show = send_message(chat_id, "(继续...)", use_card=True, receive_id_type="chat_id"), "", cut
|
||||
else:
|
||||
msg_id, last_text, show = send_message(open_id, "(继续...)", use_card=True), "", cut
|
||||
display = show if done else show + " ⏳"
|
||||
if display != last_text and msg_id:
|
||||
update_message(msg_id, display)
|
||||
last_text = display
|
||||
if done:
|
||||
_send_generated_files(open_id, raw)
|
||||
if chat_id:
|
||||
_send_generated_files(chat_id, raw, receive_id_type="chat_id")
|
||||
else:
|
||||
_send_generated_files(open_id, raw)
|
||||
break
|
||||
if not user_tasks.get(open_id, {}).get("running", True):
|
||||
send_message(open_id, "已停止")
|
||||
if chat_id:
|
||||
send_message(chat_id, "已停止", receive_id_type="chat_id")
|
||||
else:
|
||||
send_message(open_id, "已停止")
|
||||
except Exception as e:
|
||||
import traceback
|
||||
|
||||
print(f"[ERROR] run_agent 异常: {e}")
|
||||
traceback.print_exc()
|
||||
send_message(open_id, f"错误: {str(e)}")
|
||||
if chat_id:
|
||||
send_message(chat_id, f"错误: {str(e)}", receive_id_type="chat_id")
|
||||
else:
|
||||
send_message(open_id, f"错误: {str(e)}")
|
||||
finally:
|
||||
user_tasks.pop(open_id, None)
|
||||
|
||||
threading.Thread(target=run_agent, daemon=True).start()
|
||||
|
||||
|
||||
def handle_command(open_id, cmd):
|
||||
def handle_command(open_id, cmd, chat_id=None):
|
||||
def _send_cmd_response(content):
|
||||
if chat_id:
|
||||
send_message(chat_id, content, receive_id_type="chat_id")
|
||||
else:
|
||||
send_message(open_id, content)
|
||||
if cmd == "/stop":
|
||||
if open_id in user_tasks:
|
||||
user_tasks[open_id]["running"] = False
|
||||
agent.abort()
|
||||
send_message(open_id, "正在停止...")
|
||||
_send_cmd_response("正在停止...")
|
||||
elif cmd == "/new":
|
||||
agent.abort()
|
||||
agent.history = []
|
||||
send_message(open_id, "已清空当前共享上下文")
|
||||
_send_cmd_response("已清空当前共享上下文")
|
||||
elif cmd == "/help":
|
||||
send_message(open_id, "命令列表:\n/stop - 停止当前任务\n/status - 查看状态\n/restore - 恢复上次对话历史\n/new - 开启新对话\n/help - 显示帮助")
|
||||
_send_cmd_response("命令列表:\n/stop - 停止当前任务\n/status - 查看状态\n/restore - 恢复上次对话历史\n/new - 开启新对话\n/help - 显示帮助")
|
||||
elif cmd == "/status":
|
||||
send_message(open_id, f"状态: {'空闲' if not agent.is_running else '运行中'}")
|
||||
_send_cmd_response(f"状态: {'空闲' if not agent.is_running else '运行中'}")
|
||||
elif cmd == "/restore":
|
||||
try:
|
||||
files = glob.glob("./temp/model_responses_*.txt")
|
||||
if not files:
|
||||
return send_message(open_id, "没有找到历史记录")
|
||||
return _send_cmd_response("没有找到历史记录")
|
||||
latest = max(files, key=os.path.getmtime)
|
||||
with open(latest, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
@@ -515,11 +539,11 @@ def handle_command(open_id, cmd):
|
||||
agent.history.extend([f"[USER]: {u}", f"[Agent] {r}"])
|
||||
count += 1
|
||||
agent.abort()
|
||||
send_message(open_id, f"已恢复 {count} 轮对话\n来源: {os.path.basename(latest)}\n(仅恢复上下文,请输入新问题继续)")
|
||||
_send_cmd_response(f"已恢复 {count} 轮对话\n来源: {os.path.basename(latest)}\n(仅恢复上下文,请输入新问题继续)")
|
||||
except Exception as e:
|
||||
send_message(open_id, f"恢复失败: {e}")
|
||||
_send_cmd_response(f"恢复失败: {e}")
|
||||
else:
|
||||
send_message(open_id, f"未知命令: {cmd}")
|
||||
_send_cmd_response(f"未知命令: {cmd}")
|
||||
|
||||
|
||||
def main():
|
||||
|
||||
Reference in New Issue
Block a user