mirror of
https://github.com/zhayujie/chatgpt-on-wechat.git
synced 2026-03-18 04:25:14 +08:00
fix: dingtalk picture and file process
This commit is contained in:
@@ -437,38 +437,31 @@ class DingTalkChanel(ChatChannel, dingtalk_stream.ChatbotHandler):
|
|||||||
def get_image_download_url(self, download_code: str) -> str:
|
def get_image_download_url(self, download_code: str) -> str:
|
||||||
"""
|
"""
|
||||||
获取图片下载地址
|
获取图片下载地址
|
||||||
使用钉钉 API: https://open.dingtalk.com/document/orgapp/download-the-robot-to-receive-the-file
|
返回一个特殊的 URL 格式:dingtalk://download/{robot_code}:{download_code}
|
||||||
|
后续会在 download_image_file 中使用新版 API 下载
|
||||||
"""
|
"""
|
||||||
access_token = self.get_access_token()
|
# 获取 robot_code
|
||||||
if not access_token:
|
if not hasattr(self, '_robot_code_cache'):
|
||||||
logger.error("[DingTalk] Cannot get access token for image download")
|
self._robot_code_cache = None
|
||||||
|
|
||||||
|
robot_code = self._robot_code_cache
|
||||||
|
|
||||||
|
if not robot_code:
|
||||||
|
logger.error("[DingTalk] robot_code not available for image download")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
url = f"https://oapi.dingtalk.com/robot/messageFiles/download"
|
# 返回一个特殊的 URL,包含 robot_code 和 download_code
|
||||||
params = {
|
logger.info(f"[DingTalk] Successfully got image download URL for code: {download_code}")
|
||||||
"access_token": access_token,
|
return f"dingtalk://download/{robot_code}:{download_code}"
|
||||||
"downloadCode": download_code
|
|
||||||
}
|
|
||||||
|
|
||||||
try:
|
|
||||||
response = requests.get(url, params=params, timeout=10)
|
|
||||||
if response.status_code == 200:
|
|
||||||
# 返回图片的直接下载 URL(实际上这个 API 直接返回文件内容)
|
|
||||||
# 我们需要保存文件并返回本地路径
|
|
||||||
logger.info(f"[DingTalk] Successfully got image download URL for code: {download_code}")
|
|
||||||
# 返回一个特殊的 URL,包含 download_code,后续会用它来下载
|
|
||||||
return f"dingtalk://download/{download_code}"
|
|
||||||
else:
|
|
||||||
logger.error(f"[DingTalk] Failed to get image download URL: {response.text}")
|
|
||||||
return None
|
|
||||||
except Exception as e:
|
|
||||||
logger.error(f"[DingTalk] Exception getting image download URL: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
async def process(self, callback: dingtalk_stream.CallbackMessage):
|
async def process(self, callback: dingtalk_stream.CallbackMessage):
|
||||||
try:
|
try:
|
||||||
incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
|
incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
|
||||||
|
|
||||||
|
# 缓存 robot_code,用于后续图片下载
|
||||||
|
if hasattr(incoming_message, 'robot_code'):
|
||||||
|
self._robot_code_cache = incoming_message.robot_code
|
||||||
|
|
||||||
# Debug: 打印完整的 event 数据
|
# Debug: 打印完整的 event 数据
|
||||||
logger.debug(f"[DingTalk] ===== Incoming Message Debug =====")
|
logger.debug(f"[DingTalk] ===== Incoming Message Debug =====")
|
||||||
logger.debug(f"[DingTalk] callback.data keys: {callback.data.keys() if hasattr(callback.data, 'keys') else 'N/A'}")
|
logger.debug(f"[DingTalk] callback.data keys: {callback.data.keys() if hasattr(callback.data, 'keys') else 'N/A'}")
|
||||||
|
|||||||
@@ -138,48 +138,84 @@ def download_image_file(image_url, temp_dir):
|
|||||||
logger.error("[DingTalk] Missing dingtalk_client_id or dingtalk_client_secret")
|
logger.error("[DingTalk] Missing dingtalk_client_id or dingtalk_client_secret")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 获取 access_token
|
# 解析 robot_code 和 download_code
|
||||||
token_url = "https://oapi.dingtalk.com/gettoken"
|
parts = download_code.split(":", 1)
|
||||||
token_params = {
|
if len(parts) != 2:
|
||||||
"appkey": client_id,
|
logger.error(f"[DingTalk] Invalid download_code format (expected robot_code:download_code): {download_code[:50]}")
|
||||||
"appsecret": client_secret
|
return None
|
||||||
|
|
||||||
|
robot_code, actual_download_code = parts
|
||||||
|
|
||||||
|
# 获取 access_token(使用新版 API)
|
||||||
|
token_url = "https://api.dingtalk.com/v1.0/oauth2/accessToken"
|
||||||
|
token_headers = {
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
token_body = {
|
||||||
|
"appKey": client_id,
|
||||||
|
"appSecret": client_secret
|
||||||
}
|
}
|
||||||
|
|
||||||
try:
|
try:
|
||||||
token_response = requests.get(token_url, params=token_params, timeout=10)
|
token_response = requests.post(token_url, json=token_body, headers=token_headers, timeout=10)
|
||||||
token_data = token_response.json()
|
|
||||||
|
|
||||||
if token_data.get("errcode") == 0:
|
if token_response.status_code == 200:
|
||||||
access_token = token_data.get("access_token")
|
token_data = token_response.json()
|
||||||
|
access_token = token_data.get("accessToken")
|
||||||
|
|
||||||
# 下载图片
|
if not access_token:
|
||||||
download_url = f"https://oapi.dingtalk.com/robot/messageFiles/download"
|
logger.error(f"[DingTalk] Failed to get access token: {token_data}")
|
||||||
download_params = {
|
return None
|
||||||
"access_token": access_token,
|
|
||||||
"downloadCode": download_code
|
# 获取下载 URL(使用新版 API)
|
||||||
|
download_api_url = "https://api.dingtalk.com/v1.0/robot/messageFiles/download"
|
||||||
|
download_headers = {
|
||||||
|
"x-acs-dingtalk-access-token": access_token,
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}
|
||||||
|
download_body = {
|
||||||
|
"downloadCode": actual_download_code,
|
||||||
|
"robotCode": robot_code
|
||||||
}
|
}
|
||||||
|
|
||||||
response = requests.get(download_url, params=download_params, stream=True, timeout=60)
|
download_response = requests.post(download_api_url, json=download_body, headers=download_headers, timeout=10)
|
||||||
if response.status_code == 200:
|
|
||||||
# 生成文件名(使用 download_code 的 hash,避免特殊字符)
|
if download_response.status_code == 200:
|
||||||
import hashlib
|
download_data = download_response.json()
|
||||||
file_hash = hashlib.md5(download_code.encode()).hexdigest()[:16]
|
download_url = download_data.get("downloadUrl")
|
||||||
file_name = f"{file_hash}.png"
|
|
||||||
file_path = os.path.join(temp_dir, file_name)
|
|
||||||
|
|
||||||
with open(file_path, 'wb') as file:
|
if not download_url:
|
||||||
file.write(response.content)
|
logger.error(f"[DingTalk] No downloadUrl in response: {download_data}")
|
||||||
|
return None
|
||||||
|
|
||||||
logger.info(f"[DingTalk] Image downloaded successfully: {file_path}")
|
# 从 downloadUrl 下载实际图片
|
||||||
return file_path
|
image_response = requests.get(download_url, stream=True, timeout=60)
|
||||||
|
|
||||||
|
if image_response.status_code == 200:
|
||||||
|
# 生成文件名(使用 download_code 的 hash,避免特殊字符)
|
||||||
|
import hashlib
|
||||||
|
file_hash = hashlib.md5(actual_download_code.encode()).hexdigest()[:16]
|
||||||
|
file_name = f"{file_hash}.png"
|
||||||
|
file_path = os.path.join(temp_dir, file_name)
|
||||||
|
|
||||||
|
with open(file_path, 'wb') as file:
|
||||||
|
file.write(image_response.content)
|
||||||
|
|
||||||
|
logger.info(f"[DingTalk] Image downloaded successfully: {file_path}")
|
||||||
|
return file_path
|
||||||
|
else:
|
||||||
|
logger.error(f"[DingTalk] Failed to download image from URL: {image_response.status_code}")
|
||||||
|
return None
|
||||||
else:
|
else:
|
||||||
logger.error(f"[DingTalk] Failed to download image: {response.status_code}")
|
logger.error(f"[DingTalk] Failed to get download URL: {download_response.status_code}, {download_response.text}")
|
||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
logger.error(f"[DingTalk] Failed to get access token: {token_data}")
|
logger.error(f"[DingTalk] Failed to get access token: {token_response.status_code}, {token_response.text}")
|
||||||
return None
|
return None
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"[DingTalk] Exception downloading image: {e}")
|
logger.error(f"[DingTalk] Exception downloading image: {e}")
|
||||||
|
import traceback
|
||||||
|
logger.error(traceback.format_exc())
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 普通 HTTP(S) URL
|
# 普通 HTTP(S) URL
|
||||||
|
|||||||
@@ -187,9 +187,11 @@ available_setting = {
|
|||||||
"Minimax_group_id": "",
|
"Minimax_group_id": "",
|
||||||
"Minimax_base_url": "",
|
"Minimax_base_url": "",
|
||||||
"web_port": 9899,
|
"web_port": 9899,
|
||||||
"agent": False, # 是否开启Agent模式
|
"agent": True, # 是否开启Agent模式
|
||||||
"agent_workspace": "~/cow", # agent工作空间路径,用于存储skills、memory等
|
"agent_workspace": "~/cow", # agent工作空间路径,用于存储skills、memory等
|
||||||
"bocha_api_key": ""
|
"agent_max_context_tokens": 40000, # Agent模式下最大上下文tokens
|
||||||
|
"agent_max_context_turns": 30, # Agent模式下最大上下文轮次
|
||||||
|
"agent_max_steps": 20, # Agent模式下单次运行最大决策步数
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -32,9 +32,6 @@ broadscope_bailian
|
|||||||
# google
|
# google
|
||||||
google-generativeai
|
google-generativeai
|
||||||
|
|
||||||
# dingtalk
|
|
||||||
dingtalk_stream
|
|
||||||
|
|
||||||
# zhipuai
|
# zhipuai
|
||||||
zhipuai>=2.0.1
|
zhipuai>=2.0.1
|
||||||
|
|
||||||
|
|||||||
@@ -14,4 +14,6 @@ PyYAML>=6.0
|
|||||||
croniter>=2.0.0
|
croniter>=2.0.0
|
||||||
|
|
||||||
# feishu websocket mode
|
# feishu websocket mode
|
||||||
lark-oapi
|
lark-oapi
|
||||||
|
# dingtalk
|
||||||
|
dingtalk_stream
|
||||||
|
|||||||
Reference in New Issue
Block a user