飞书应用机器人@影刀技术问答助理的python代码
·
飞书应用机器人@影刀技术问答助理的python代码
# -*- coding: utf-8 -*-
"""
在指定消息下创建话题,并 @技术问答助理
================================================================
场景:运营助理已发送卡片消息(拿到 message_id),
在该消息下创建话题,话题里第一条消息带上 @技术问答助理 + 用户原文 + 图片,
让技术问答助理通过事件订阅收到并开始处理。
依赖:pip install requests
参考自 cyber-monkey 项目:
- handlers.py:318 _build_forward_post() ← 拼装 post 内容(@+文+图)
- messages.py:342 upload_image() ← 上传图片拿 image_key
- messages.py:79 reply API + reply_in_thread ← 创建话题
"""
import requests
import json
import os
from typing import List, Optional
# try:
# from xbot.app.logging import trace as print
# except:
# from xbot import print
# ==================== 飞书 API 封装 ====================
def _get_tenant_token(app_id: str, app_secret: str) -> str:
"""获取飞书租户凭证(tenant_access_token)"""
url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
payload = {"app_id": app_id, "app_secret": app_secret}
resp = requests.post(url, json=payload, timeout=10)
resp.raise_for_status()
data = resp.json()
if data.get("code") != 0:
raise Exception(f"获取 Token 失败: {data.get('msg')}")
return data["tenant_access_token"]
def _upload_image(token: str, image_path: str) -> str:
"""
上传图片到飞书,拿到 image_key。
对应 cyber-monkey/messages.py:342 的 upload_image()
"""
url = "https://open.feishu.cn/open-apis/im/v1/images"
headers = {"Authorization": f"Bearer {token}"}
# image_type=message 表示这张图是用来发消息的
data = {"image_type": "message"}
with open(image_path, "rb") as f:
files = {"image": (os.path.basename(image_path), f, "image/png")}
resp = requests.post(url, headers=headers, data=data, files=files, timeout=30)
resp.raise_for_status()
res = resp.json()
if res.get("code") != 0:
raise Exception(f"上传图片失败: {res.get('msg')}")
return res["data"]["image_key"]
def _reply_in_thread(token: str, message_id: str, post_content: dict) -> str:
"""
在指定消息下创建话题并回复。
对应飞书 API: POST /im/v1/messages/{message_id}/reply (reply_in_thread=true)
参数:
token : tenant_access_token
message_id : 要在其下创建话题的那条消息的 ID(通常是卡片消息的 message_id)
post_content: post 富文本内容
返回:
新消息的 message_id
"""
url = f"https://open.feishu.cn/open-apis/im/v1/messages/{message_id}/reply"
headers = {
"Authorization": f"Bearer {token}",
"Content-Type": "application/json",
}
payload = {
"content": json.dumps(post_content, ensure_ascii=False),
"msg_type": "post",
"reply_in_thread": True, # ← 关键:创建话题
}
resp = requests.post(url, headers=headers, json=payload, timeout=10)
resp.raise_for_status()
res = resp.json()
if res.get("code") != 0:
raise Exception(f"创建话题失败: {res.get('msg')}")
return res["data"]["message_id"]
# ==================== 核心逻辑 ====================
def _build_post_content(
tech_bot_open_id: str,
text_content: str,
image_keys: List[str],
title: str = "",
) -> dict:
"""
构造 post(富文本)消息体。
对应 cyber-monkey/handlers.py:318 的 _build_forward_post()
结构:
[[@bot], [正文], [图片1], [图片2], ...]
每个 block 是一个 list,飞书要求 content 是 [[block1], [block2], ...] 嵌套结构。
"""
content = []
# Block 1:@技术问答助理(最前面,触发 mentions 路由)
content.append([{"tag": "at", "user_id": tech_bot_open_id}])
# Block 2:用户原文
if text_content:
content.append([{"tag": "text", "text": text_content}])
# Block 3+:图片(每张图一个独立 block)
for img_key in image_keys:
content.append([{"tag": "img", "image_key": img_key}])
return {"zh_cn": {"title": title, "content": content}}
def send_to_tech_assistant(app_id, app_secret, message_id, tech_bot_open_id, text_content, image_paths):
"""
title: 在消息下创建话题并@技术问答助理
description: 在指定的消息 %message_id% 下创建话题,话题第一条消息带上 @技术问答助理 + 用户原文 %text_content% + 图片,让技术问答助理通过事件订阅收到并开始处理。
inputs:
- app_id (str): 运营助理应用的 App ID,eg: "cli_a5db1166713a900c"
- app_secret (str): 运营助理应用的 App Secret,eg: "Imdfwys4jb2VanubbZpoqd1elIhnItKy"
- message_id (str): 要在其下创建话题的消息 ID(通常是卡片消息发送后返回的 message_id),eg: "om_x100b6706f8c124a4b0350002e54450b"
- tech_bot_open_id (str): 技术问答助理机器人的 open_id(ou_ 开头),eg: "ou_180d04de9af8f925124332453f441473"
- text_content (str): 用户问题原文,eg: "修改应用信息处的标签怎么设置,没有可选项"
- image_paths (list): 本地图片路径列表,eg: ["D:\\Desktop\\1.png"]
outputs:
- message_id (str): 创建话题后返回的消息 ID,eg: "om_bc564911586866593607429846077ffa"
"""
# 1. 获取 Token
token = _get_tenant_token(app_id, app_secret)
# 2. 上传所有图片,拿到 image_key 列表
image_keys: List[str] = []
if image_paths:
for path in image_paths:
if not os.path.exists(path):
raise FileNotFoundError(f"图片不存在: {path}")
image_key = _upload_image(token, path)
image_keys.append(image_key)
print(f"图片已上传: {path} -> {image_key}")
# 3. 构造 post 富文本内容(@bot + 原文 + 图片)
post_content = _build_post_content(
tech_bot_open_id=tech_bot_open_id,
text_content=text_content,
image_keys=image_keys,
)
# 4. 在 message_id 对应的消息下创建话题 + @技术问答助理
new_message_id = _reply_in_thread(
token=token,
message_id=message_id,
post_content=post_content,
)
print(f"话题已创建并 @技术问答助理,消息 message_id={new_message_id}")
return new_message_id
# ==================== 影刀调用入口 ====================
# 使用此指令前,请确保安装必要的 Python 库,例如使用以下命令安装:
# pip install requests
# === 填写你的实际参数 ===
APP_ID = "XX"
APP_SECRET = "XXX"
# 卡片消息发送后返回的 message_id(在这条消息下创建话题)
MESSAGE_ID = "XXX"
# 技术问答助理的 open_id(@的对象)
TECH_BOT_OPEN_ID = "XXX"
# 用户原始问题
USER_TEXT = "修改应用信息处的标签怎么设置,没有可选项"
# 用户原始图片(本地路径,没有就传 None)
USER_IMAGES = [
r"D:\Desktop\1.png",
# r"C:\path\to\screenshot2.png", # 多张图就继续加
]
# === 执行 ===
message_id = send_to_tech_assistant(
app_id=APP_ID,
app_secret=APP_SECRET,
message_id=MESSAGE_ID,
tech_bot_open_id=TECH_BOT_OPEN_ID,
text_content=USER_TEXT,
image_paths=USER_IMAGES,
)
# 影刀组件输出
output = message_id
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐




所有评论(0)