Przeglądaj źródła

视频发送

develop
H Vs 2 miesięcy temu
rodzic
commit
6373d4fa82
6 zmienionych plików z 406 dodań i 102 usunięć
  1. +73
    -1
      common/utils.py
  2. +1
    -1
      docker/Dockerfile.latest
  3. +5
    -1
      requirements.txt
  4. +236
    -97
      resources/messages_resource.py
  5. +58
    -2
      wechat/biz.py
  6. +33
    -0
      wechat/gewe_chat.py

+ 73
- 1
common/utils.py Wyświetl plik

@@ -10,6 +10,12 @@ from urllib.parse import urlparse, unquote
from voice.ali.ali_voice import AliVoice
from voice import audio_convert


import cv2
import os
import tempfile
from moviepy import VideoFileClip

from common import redis_helper

from datetime import datetime
@@ -339,4 +345,70 @@ def get_login_info_by_wxid(wxid: str) ->dict:
if cursor == 0:
break
return None,None
return None,None


def download_video_and_get_thumbnail(url, thumbnail_path):
"""
从指定URL下载MP4视频,提取首帧作为缩略图,并返回缩略图路径及视频时长。
参数:
url (str): 视频的URL地址。
thumbnail_path (str): 缩略图的保存路径。
返回:
tuple: (缩略图路径, 视频时长(秒))
异常:
可能抛出requests.exceptions.RequestException,cv2.error,IOError等异常。
"""
# 创建临时目录以下载视频
with tempfile.TemporaryDirectory() as tmp_dir:
# 下载视频到临时文件
video_path = os.path.join(tmp_dir, 'temp_video.mp4')
response = requests.get(url, stream=True)
response.raise_for_status() # 确保请求成功
with open(video_path, 'wb') as f:
for chunk in response.iter_content(chunk_size=8192):
if chunk: # 过滤掉保持连接的空白块
f.write(chunk)
# 提取视频首帧作为缩略图
vidcap = cv2.VideoCapture(video_path)
success, image = vidcap.read()
vidcap.release()
if not success:
raise RuntimeError("无法读取视频的首帧,请检查视频文件是否有效。")
# 确保缩略图的目录存在
thumbnail_dir = os.path.dirname(thumbnail_path)
if thumbnail_dir:
os.makedirs(thumbnail_dir, exist_ok=True)
# 保存缩略图
cv2.imwrite(thumbnail_path, image)
# 使用moviepy计算视频时长
clip = VideoFileClip(video_path)
duration = clip.duration
clip.close()

# OSS 配置(建议将凭证存储在安全的地方)
oss_access_key_id="LTAI5tRTG6pLhTpKACJYoPR5"
oss_access_key_secret="E7dMzeeMxq4VQvLg7Tq7uKf3XWpYfN"
oss_endpoint="http://oss-cn-shanghai.aliyuncs.com"
oss_bucket_name="cow-agent"
oss_prefix="cow"

# 上传文件到 OSS
file_path = thumbnail_path
file_url = upload_oss(oss_access_key_id, oss_access_key_secret, oss_endpoint, oss_bucket_name, file_path, oss_prefix)
# 删除临时文件
try:
os.remove(thumbnail_path)
except FileNotFoundError:
pass # 如果文件未找到,跳过删除

return file_url, duration

+ 1
- 1
docker/Dockerfile.latest Wyświetl plik

@@ -25,7 +25,7 @@ RUN apt-get update \
&& cd ${BUILD_PREFIX} \
&& cp config-template.json config.json \
&& /usr/local/bin/python -m pip install --no-cache --upgrade pip \
&& pip install --no-cache -r requirements.txt
&& pip install --no-cache -r requirements.txt -i https://mirrors.tuna.tsinghua.edu.cn/pypi/web/simple

WORKDIR ${BUILD_PREFIX}



+ 5
- 1
requirements.txt Wyświetl plik

@@ -42,4 +42,8 @@ pysilk-mod
#pip3 install pysilk-mod

oss2
gunicorn
gunicorn


opencv-python
moviepy

+ 236
- 97
resources/messages_resource.py Wyświetl plik

@@ -6,12 +6,16 @@ from voice.ali.ali_voice import AliVoice
from common import utils,redis_helper,memory,kafka_helper
from common.log import logger
import xml.etree.ElementTree as ET
import threading,time


import os

from voice import audio_convert


timeout_duration = 4.0

class MessagesResource(Resource):
def __init__(self):
self.parser = reqparse.RequestParser()
@@ -37,25 +41,33 @@ class MessagesResource(Resource):
to_wxid = msg_data["ToUserName"]["string"]
msg_push_content=msg_data.get("PushContent") #群发

handlers = {
1: handle_text,
3: handle_image,
34: handle_voice,
49: handle_xml,
37: handle_add_friend_notice,
10002: handle_10002_msg
}
# (扫码进群情况)判断受否是群聊,并添加到通信录,
if check_chatroom(from_wxid) or check_chatroom(to_wxid):
logger.info('群信息')
chatroom_id=from_wxid
ret,msg,data=gewe_chat.wxchat.save_contract_list(token_id,app_id,chatroom_id,3)
logger.info(f'保存到通讯录 chatroom_id {chatroom_id} {msg}')
gewe_chat.wxchat.update_groups_info_to_cache(token_id,app_id,wxid,chatroom_id)
handlers[1]=handle_text_group
handlers[3]=handle_image_group
handlers[34]=handle_voice_group
wx_config = gewe_chat.wxchat.get_wxchat_config_from_cache(wxid)
if not bool(wx_config.get("agentEnabled",False)):
logger.warning(f'{wxid} 智能体已关闭')
handlers = {
49: handle_xml,
37: handle_add_friend_notice,
10002: handle_10002_msg
}
else:
handlers = {
1: handle_text,
3: handle_image,
34: handle_voice,
49: handle_xml,
37: handle_add_friend_notice,
10002: handle_10002_msg
}
# (扫码进群情况)判断受否是群聊,并添加到通信录
if check_chatroom(from_wxid) or check_chatroom(to_wxid):
logger.info('群信息')
chatroom_id=from_wxid
ret,msg,data=gewe_chat.wxchat.save_contract_list(token_id,app_id,chatroom_id,3)
logger.info(f'保存到通讯录 chatroom_id {chatroom_id} {msg}')
gewe_chat.wxchat.update_groups_info_to_cache(token_id,app_id,wxid,chatroom_id)
handlers[1]=handle_text_group
handlers[3]=handle_image_group
handlers[34]=handle_voice_group

handler = handlers.get(msg_type)
if handler:
@@ -115,94 +127,216 @@ def handle_text(token_id,app_id, wxid,msg_data,from_wxid, to_wxid):
logger.info("发送对话 %s",input_message)
else:
callback_to_user=msg_data["FromUserName"]["string"]
hash_key = f'__AI_OPS_WX__:MESSAGES:{wxid}:{callback_to_user}'
prompt={"role": "user", "content": [{
"type": "text",
"text": msg_content
}]}
messages_to_send=gewe_chat.wxchat.save_session_messages_to_cache(hash_key, prompt)
# 收到的对话
input_wx_content_dialogue_message=[{"type": "text", "text": msg_content}]
input_message=utils.dialogue_message(callback_to_user,wxid,input_wx_content_dialogue_message)
kafka_helper.kafka_client.produce_message(input_message)
logger.info("发送对话 %s",input_message)
# hash_key = f'__AI_OPS_WX__:MESSAGES:{wxid}:{callback_to_user}'
# prompt={"role": "user", "content": [{
# "type": "text",
# "text": msg_content
# }]}
# messages_to_send=gewe_chat.wxchat.save_session_messages_to_cache(hash_key, prompt)
# # 收到的对话
# input_wx_content_dialogue_message=[{"type": "text", "text": msg_content}]
# input_message=utils.dialogue_message(callback_to_user,wxid,input_wx_content_dialogue_message)
# kafka_helper.kafka_client.produce_message(input_message)
# logger.info("发送对话 %s",input_message)
cache_data = memory.USER_INTERACTIVE_CACHE.get(wxid)
if cache_data and cache_data.get('interactive') :
o=get_first_char_if_digit(msg_content)
if o is not None:
userSelectOptions=cache_data.get('options')
if o < len(userSelectOptions):
o=o-1
msg_content=userSelectOptions[o].get("value")
messages_to_send=[{"role": "user", "content": msg_content}]
else:
messages_to_send=[{"role": "user", "content": msg_content}]
else:
messages_to_send=[{"role": "user", "content": msg_content}]
# cache_data = memory.USER_INTERACTIVE_CACHE.get(wxid)
# if cache_data and cache_data.get('interactive') :
# o=get_first_char_if_digit(msg_content)
# if o is not None:
# userSelectOptions=cache_data.get('options')
# if o < len(userSelectOptions):
# o=o-1
# msg_content=userSelectOptions[o].get("value")
# messages_to_send=[{"role": "user", "content": msg_content}]
# else:
# messages_to_send=[{"role": "user", "content": msg_content}]
# else:
# messages_to_send=[{"role": "user", "content": msg_content}]
res=fast_gpt_api(messages_to_send,wxid,callback_to_user)
reply_content=res["choices"][0]["message"]["content"]
# res=fast_gpt_api(messages_to_send,wxid,callback_to_user)
# reply_content=res["choices"][0]["message"]["content"]
description = ''
userSelectOptions = []
if isinstance(reply_content, list) and any(item.get("type") == "interactive" for item in reply_content):
for item in reply_content:
if item["type"] == "interactive" and item["interactive"]["type"] == "userSelect":
params = item["interactive"]["params"]
description = params.get("description")
userSelectOptions = params.get("userSelectOptions", [])
values_string = "\n".join(option["value"] for option in userSelectOptions)
# description = ''
# userSelectOptions = []
# if isinstance(reply_content, list) and any(item.get("type") == "interactive" for item in reply_content):
# for item in reply_content:
# if item["type"] == "interactive" and item["interactive"]["type"] == "userSelect":
# params = item["interactive"]["params"]
# description = params.get("description")
# userSelectOptions = params.get("userSelectOptions", [])
# values_string = "\n".join(option["value"] for option in userSelectOptions)
if description is not None:
memory.USER_INTERACTIVE_CACHE[wxid] = {
"interactive":True,
"options": userSelectOptions,
}
reply_content=description + '------------------------------\n'+values_string
# if description is not None:
# memory.USER_INTERACTIVE_CACHE[wxid] = {
# "interactive":True,
# "options": userSelectOptions,
# }
# reply_content=description + '------------------------------\n'+values_string
elif isinstance(reply_content, list) and any(item.get("type") == "text" for item in reply_content):
memory.USER_INTERACTIVE_CACHE[wxid] = {
"interactive":False
}
text=''
for item in reply_content:
if item["type"] == "text":
text=item["text"]["content"]
if text=='':
# 去除上次上一轮对话再次请求
cache_messages_str=redis_helper.redis_helper.get_hash_field(hash_key,"data")
cache_messages = json.loads(cache_messages_str) if cache_messages_str else []
# elif isinstance(reply_content, list) and any(item.get("type") == "text" for item in reply_content):
# memory.USER_INTERACTIVE_CACHE[wxid] = {
# "interactive":False
# }
# text=''
# for item in reply_content:
# if item["type"] == "text":
# text=item["text"]["content"]
# if text=='':
# # 去除上次上一轮对话再次请求
# cache_messages_str=redis_helper.redis_helper.get_hash_field(hash_key,"data")
# cache_messages = json.loads(cache_messages_str) if cache_messages_str else []
if len(cache_messages) >= 3:
cache_messages = cache_messages[:-3]
# if len(cache_messages) >= 3:
# cache_messages = cache_messages[:-3]

# redis_helper.redis_helper.update_hash_field(hash_key,"data",json.dumps(cache_messages,ensure_ascii=False))
# messages_to_send=gewe_chat.wxchat.save_session_messages_to_cache(hash_key, prompt)
# res=fast_gpt_api(messages_to_send,wxid,callback_to_user)
# reply_content=res["choices"][0]["message"]["content"]


# if isinstance(reply_content, list) :
# reply_content=reply_content[0].get('text').get("content")

# else:
# reply_content=text
# else:
# memory.USER_INTERACTIVE_CACHE[wxid] = {
# "interactive":False
# }
# reply_content=res["choices"][0]["message"]["content"]

# gewe_chat.wxchat.post_text(token_id,app_id,callback_to_user,reply_content)
# gewe_chat.wxchat.save_session_messages_to_cache(hash_key, {"role": "assistant", "content": reply_content})
# # 回复的对话
# input_wx_content_dialogue_message=[{"type": "text", "text": reply_content}]
# input_message=utils.dialogue_message(wxid,callback_to_user,input_wx_content_dialogue_message,True)
# kafka_helper.kafka_client.produce_message(input_message)
# logger.info("发送对话 %s",input_message)
# 创建并启动任务线程,将参数传递给 ai_chat_text 函数
task_thread = threading.Thread(
target=ai_chat_text,
args=(token_id,app_id,wxid,msg_data,msg_content)
)
task_thread.start()

# 设置定时器,1秒后检查任务是否超时。这里需要使用 lambda 来传递参数
timeout_timer = threading.Timer(
timeout_duration,
lambda:check_timeout(task_thread, token_id, app_id, callback_to_user)
)
timeout_timer.start()

# 等待任务线程完成
task_thread.join()
# 取消定时器
timeout_timer.cancel()

def check_timeout( task_thread:threading.Thread, token_id, app_id, callback_to_user):
if task_thread.is_alive():
print(f"任务运行时间超过{timeout_duration}秒,token_id={token_id}, app_id={app_id}, callback_to_user={callback_to_user}")
gewe_chat.wxchat.post_text(token_id,app_id,callback_to_user,"亲,我正在组织回复的信息,请稍等一会")

def ai_chat_text(token_id,app_id,wxid,msg_data,msg_content):
start_time = time.time() # 记录任务开始时间

callback_to_user=msg_data["FromUserName"]["string"]
hash_key = f'__AI_OPS_WX__:MESSAGES:{wxid}:{callback_to_user}'

redis_helper.redis_helper.update_hash_field(hash_key,"data",json.dumps(cache_messages,ensure_ascii=False))
messages_to_send=gewe_chat.wxchat.save_session_messages_to_cache(hash_key, prompt)
res=fast_gpt_api(messages_to_send,wxid,callback_to_user)
reply_content=res["choices"][0]["message"]["content"]
prompt={"role": "user", "content": [{
"type": "text",
"text": msg_content
}]}
messages_to_send=gewe_chat.wxchat.save_session_messages_to_cache(hash_key, prompt)
# 收到的对话
input_wx_content_dialogue_message=[{"type": "text", "text": msg_content}]
input_message=utils.dialogue_message(callback_to_user,wxid,input_wx_content_dialogue_message)
kafka_helper.kafka_client.produce_message(input_message)
logger.info("发送对话 %s",input_message)
cache_data = memory.USER_INTERACTIVE_CACHE.get(wxid)
if cache_data and cache_data.get('interactive') :
o=get_first_char_if_digit(msg_content)
if o is not None:
userSelectOptions=cache_data.get('options')
if o < len(userSelectOptions):
o=o-1
msg_content=userSelectOptions[o].get("value")
messages_to_send=[{"role": "user", "content": msg_content}]
else:
messages_to_send=[{"role": "user", "content": msg_content}]
else:
messages_to_send=[{"role": "user", "content": msg_content}]
res=fast_gpt_api(messages_to_send,wxid,callback_to_user)

reply_content=res["choices"][0]["message"]["content"]

description = ''
userSelectOptions = []

if isinstance(reply_content, list) and any(item.get("type") == "interactive" for item in reply_content):
for item in reply_content:
if item["type"] == "interactive" and item["interactive"]["type"] == "userSelect":
params = item["interactive"]["params"]
description = params.get("description")
userSelectOptions = params.get("userSelectOptions", [])
values_string = "\n".join(option["value"] for option in userSelectOptions)
if description is not None:
memory.USER_INTERACTIVE_CACHE[wxid] = {
"interactive":True,
"options": userSelectOptions,
}
reply_content=description + '------------------------------\n'+values_string
elif isinstance(reply_content, list) and any(item.get("type") == "text" for item in reply_content):
memory.USER_INTERACTIVE_CACHE[wxid] = {
"interactive":False
}
text=''
for item in reply_content:
if item["type"] == "text":
text=item["text"]["content"]
if text=='':
# 去除上次上一轮对话再次请求
cache_messages_str=redis_helper.redis_helper.get_hash_field(hash_key,"data")
cache_messages = json.loads(cache_messages_str) if cache_messages_str else []
if len(cache_messages) >= 3:
cache_messages = cache_messages[:-3]

redis_helper.redis_helper.update_hash_field(hash_key,"data",json.dumps(cache_messages,ensure_ascii=False))
messages_to_send=gewe_chat.wxchat.save_session_messages_to_cache(hash_key, prompt)
res=fast_gpt_api(messages_to_send,wxid,callback_to_user)
reply_content=res["choices"][0]["message"]["content"]

if isinstance(reply_content, list) :
reply_content=reply_content[0].get('text').get("content")

else:
reply_content=text
if isinstance(reply_content, list) :
reply_content=reply_content[0].get('text').get("content")

else:
memory.USER_INTERACTIVE_CACHE[wxid] = {
"interactive":False
}
reply_content=res["choices"][0]["message"]["content"]
reply_content=text
else:
memory.USER_INTERACTIVE_CACHE[wxid] = {
"interactive":False
}
reply_content=res["choices"][0]["message"]["content"]

gewe_chat.wxchat.post_text(token_id,app_id,callback_to_user,reply_content)
gewe_chat.wxchat.save_session_messages_to_cache(hash_key, {"role": "assistant", "content": reply_content})
# 回复的对话
input_wx_content_dialogue_message=[{"type": "text", "text": reply_content}]
input_message=utils.dialogue_message(wxid,callback_to_user,input_wx_content_dialogue_message,True)
kafka_helper.kafka_client.produce_message(input_message)
logger.info("发送对话 %s",input_message)
end_time = time.time() # 记录任务结束时间
execution_time = end_time - start_time # 计算执行时间
logger.info(f"AI回答任务完成,耗时 {execution_time:.2f} 秒")

gewe_chat.wxchat.post_text(token_id,app_id,callback_to_user,reply_content)
gewe_chat.wxchat.save_session_messages_to_cache(hash_key, {"role": "assistant", "content": reply_content})
# 回复的对话
input_wx_content_dialogue_message=[{"type": "text", "text": reply_content}]
input_message=utils.dialogue_message(wxid,callback_to_user,input_wx_content_dialogue_message,True)
kafka_helper.kafka_client.produce_message(input_message)
logger.info("发送对话 %s",input_message)

def handle_text_group(token_id,app_id, wxid,msg_data,from_wxid, to_wxid):
'''
@@ -396,8 +530,13 @@ def handle_voice(token_id,app_id, wxid,msg_data,from_wxid, to_wxid):
has_url=contains_url(ai_res_content)
if not has_url:
voice_during,voice_url=utils.wx_voice(ai_res_content)
ret,ret_msg,res=gewe_chat.wxchat.post_voice(token_id,app_id,callback_to_user,voice_url,voice_during)

if voice_during < 60 * 1000:
ret,ret_msg,res=gewe_chat.wxchat.post_voice(token_id,app_id,callback_to_user,voice_url,voice_during)
else:
ret,ret_msg,res=gewe_chat.wxchat.post_text(token_id,app_id,callback_to_user,ai_res_content)
logger.warning(f'回应语音消息长度 {voice_during/1000}秒,超过60秒,转为文本回复')
if ret==200:
logger.info((f'{wxid} 向 {callback_to_user} 发送语音文本【{ai_res_content}】{ret_msg}'))



+ 58
- 2
wechat/biz.py Wyświetl plik

@@ -1,7 +1,7 @@
import threading

from common import kafka_helper,redis_helper,utils
from urllib.parse import urlparse, unquote
import json,time,re,random,os
from common.log import logger, log_exception
from datetime import datetime
@@ -69,6 +69,7 @@ def process_group_sending_v0(wxchat:gewe_chat.GeWeChatCom, content_data, agent_t
send_tts_message(wxchat, token_id, app_id, agent_wxid, intersection_wxids, wx_content["text"])



def process_group_sending(wxchat:gewe_chat.GeWeChatCom, content_data, agent_tel:str):
# 获取登录信息
hash_key = f"__AI_OPS_WX__:LOGININFO:{agent_tel}"
@@ -112,7 +113,10 @@ def process_group_sending(wxchat:gewe_chat.GeWeChatCom, content_data, agent_tel:
# send_image_message(wxchat, token_id, app_id, agent_wxid, intersection_wxids, wx_content.get("image_url", {}).get("url"))
# elif wx_content["type"] == "tts":
# send_tts_message(wxchat, token_id, app_id, agent_wxid, intersection_wxids, wx_content["text"])
wxchat.forward_video_aeskey = ''
wxchat.forward_video_cdnvideourl = ''
wxchat.forward_video_length = 0

for intersection_wxid in intersection_wxids:
for wx_content in wx_content_list:
if wx_content["type"] == "text":
@@ -121,6 +125,8 @@ def process_group_sending(wxchat:gewe_chat.GeWeChatCom, content_data, agent_tel:
send_image_message(wxchat, token_id, app_id, agent_wxid, [intersection_wxid], wx_content.get("image_url", {}).get("url"))
elif wx_content["type"] == "tts":
send_tts_message(wxchat, token_id, app_id, agent_wxid, [intersection_wxid], wx_content["text"])
elif wx_content["type"] == "file":
send_file_message(wxchat, token_id, app_id, agent_wxid, [intersection_wxid], wx_content.get("file_url", {}).get("url"))



@@ -211,6 +217,56 @@ def send_tts_message(wxchat:gewe_chat.GeWeChatCom, token_id, app_id, agent_wxid,
# 等待随机时间
time.sleep(random.uniform(5, 15))

def send_file_message(wxchat:gewe_chat.GeWeChatCom, token_id, app_id, agent_wxid, intersection_wxids, file_url):

parsed_url = urlparse(file_url)
path = parsed_url.path
# 从路径中提取文件名
filename = path.split('/')[-1]
# 获取扩展名
_, ext = os.path.splitext(filename)

if ext == '.mp4':
send_video_message(wxchat, token_id, app_id, agent_wxid, intersection_wxids, file_url)
else:
send_other_file_message(wxchat, token_id, app_id, agent_wxid, intersection_wxids, file_url)
#time.sleep(random.uniform(5, 15))


def send_video_message(wxchat:gewe_chat.GeWeChatCom, token_id, app_id, agent_wxid, intersection_wxids, file_url):
for t in intersection_wxids:
# 发送视频消息
parsed_url = urlparse(file_url)
filename = os.path.basename(parsed_url.path)
tmp_file_path = os.path.join(os.getcwd(),'tmp', filename) # 拼接完整路径
thumbnail_path=tmp_file_path.replace('.mp4','.jpg')
video_duration,video_thumb_url =utils.download_video_and_get_thumbnail(file_url,thumbnail_path)

if wxchat.forward_video_aeskey == '':
ret,ret_msg,res = wxchat.post_video(token_id, app_id, t, file_url,video_thumb_url,video_duration)
if ret==200:
wxchat.forward_video_aeskey = res["aesKey"]
wxchat.forward_video_cdnvideourl = res["cdnVideoUrl"]
wxchat.forward_video_length = res["length"]
else:
ret,ret_msg,res = wxchat.forward_video(token_id, app_id, t, wxchat.forward_video_aeskey, wxchat.forward_video_cdnvideourl, wxchat.forward_video_length)
print('转发视频')
if ret==200:
logger.info(f'{agent_wxid} 向 {t} 发送视频【{file_url}】{ret_msg}')
# 构造对话消息并发送到 Kafka
input_wx_content_dialogue_message = [{"type": "file", "file_url": {"url": file_url}}]
input_message = utils.dialogue_message(agent_wxid, t, input_wx_content_dialogue_message)
kafka_helper.kafka_client.produce_message(input_message)
logger.info("发送对话 %s", input_message)
else:
logger.warning((f'{agent_wxid} 向 {t} 发送视频【{file_url}】{ret_msg}'))
# 等待随机时间
time.sleep(random.uniform(5, 15))

def send_other_file_message(wxchat:gewe_chat.GeWeChatCom, token_id, app_id, agent_wxid, intersection_wxids, file_url):
print('send_otherfile_message')

def clean_json_string(json_str):

# 删除所有控制字符(非打印字符),包括换行符、回车符等


+ 33
- 0
wechat/gewe_chat.py Wyświetl plik

@@ -337,6 +337,23 @@ class GeWeChatCom:
response_object = response.json()
return response_object.get('ret',None),response_object.get('msg',None),response_object.get('data',None)

def post_video(self,token_id,app_id,to_wxid,video_url,video_thumb_url,video_duration):
api_url = f"{self.base_url}/v2/api/message/postVideo"
headers = {
'X-GEWE-TOKEN': token_id,
'Content-Type': 'application/json'
}
data = {
"appId": app_id,
"toWxid": to_wxid,
"videoUrl": video_url,
"videoDuration":video_duration,
"videoThumbUrl":video_thumb_url
}
response = requests.post(url=api_url, headers=headers, data=json.dumps(data))
response_object = response.json()
return response_object.get('ret',None),response_object.get('msg',None),response_object.get('data',None)

def forward_image(self,token_id,app_id,to_wxid,aeskey,cdnthumburl,cdnthumblength,cdnthumbheight,cdnthumbwidth,length,md5):
api_url = f"{self.base_url}/v2/api/message/forwardImage"
headers = {
@@ -353,6 +370,22 @@ class GeWeChatCom:
response_object = response.json()
return response_object.get('data',None),response_object.get('ret',None),response_object.get('msg',None)

def forward_video(self,token_id,app_id,to_wxid,aeskey,cdnvideourl,length):
api_url = f"{self.base_url}/v2/api/message/forwardVideo"
headers = {
'X-GEWE-TOKEN': token_id,
'Content-Type': 'application/json'
}
data = {
"appId": app_id,
"toWxid": to_wxid,
"xml": f"<?xml version=\"1.0\"?>\n<msg>\n\t<videomsg aeskey=\"{aeskey}\" cdnvideourl=\"{cdnvideourl}\" cdnthumbaeskey=\"{aeskey}\" cdnthumburl=\"{cdnvideourl}\" length=\"{length}\" playlength=\"7\" cdnthumblength=\"8192\" cdnthumbwidth=\"135\" cdnthumbheight=\"240\" fromusername=\"zhangchuan2288\" md5=\"8804c121e9db91dd844f7a34035beb88\" newmd5=\"\" isplaceholder=\"0\" rawmd5=\"\" rawlength=\"0\" cdnrawvideourl=\"\" cdnrawvideoaeskey=\"\" overwritenewmsgid=\"0\" originsourcemd5=\"\" isad=\"0\" />\n</msg>"
}
response = requests.post(url=api_url, headers=headers, data=json.dumps(data))
response_object = response.json()
return response_object.get('data',None),response_object.get('ret',None),response_object.get('msg',None)

def add_contacts(self,token_id:str,app_id:str,scene:int,option:int,v3:str,v4:str,content:str):
api_url = f"{self.base_url}/v2/api/contacts/addContacts"
headers = {


Ładowanie…
Anuluj
Zapisz