diff --git a/channel/wechatmp/passive_reply.py b/channel/wechatmp/passive_reply.py index 7f4ee550a..d03efc4d1 100644 --- a/channel/wechatmp/passive_reply.py +++ b/channel/wechatmp/passive_reply.py @@ -49,7 +49,7 @@ def POST(self): # New request if ( - from_user not in channel.cache_dict + channel.cache_dict.get(from_user) is None and from_user not in channel.running or content.startswith("#") and message_id not in channel.request_cnt # insert the godcmd @@ -131,8 +131,10 @@ def POST(self): # Only one request can access to the cached data try: - (reply_type, reply_content) = channel.cache_dict.pop(from_user) - except KeyError: + (reply_type, reply_content) = channel.cache_dict[from_user].pop(0) + if not channel.cache_dict[from_user]: # If popping the message makes the list empty, delete the user entry from cache + del channel.cache_dict[from_user] + except IndexError: return "success" if reply_type == "text": @@ -146,7 +148,7 @@ def POST(self): max_split=1, ) reply_text = splits[0] + continue_text - channel.cache_dict[from_user] = ("text", splits[1]) + channel.cache_dict[from_user].append(("text", splits[1])) logger.info( "[wechatmp] Request {} do send to {} {}: {}\n{}".format( diff --git a/channel/wechatmp/wechatmp_channel.py b/channel/wechatmp/wechatmp_channel.py index 6f21ce112..2ae88228f 100644 --- a/channel/wechatmp/wechatmp_channel.py +++ b/channel/wechatmp/wechatmp_channel.py @@ -10,6 +10,7 @@ import web from wechatpy.crypto import WeChatCrypto from wechatpy.exceptions import WeChatClientException +from collections import defaultdict from bridge.context import * from bridge.reply import * @@ -46,7 +47,7 @@ def __init__(self, passive_reply=True): self.crypto = WeChatCrypto(token, aes_key, appid) if self.passive_reply: # Cache the reply to the user's first message - self.cache_dict = dict() + self.cache_dict = defaultdict(list) # Record whether the current message is being processed self.running = set() # Count the request from wechat official server by message_id @@ -82,24 +83,28 @@ def send(self, reply: Reply, context: Context): if reply.type == ReplyType.TEXT or reply.type == ReplyType.INFO or reply.type == ReplyType.ERROR: reply_text = reply.content logger.info("[wechatmp] text cached, receiver {}\n{}".format(receiver, reply_text)) - self.cache_dict[receiver] = ("text", reply_text) + self.cache_dict[receiver].append(("text", reply_text)) elif reply.type == ReplyType.VOICE: - try: - voice_file_path = reply.content - with open(voice_file_path, "rb") as f: - # support: <2M, <60s, mp3/wma/wav/amr - response = self.client.material.add("voice", f) - logger.debug("[wechatmp] upload voice response: {}".format(response)) - # 根据文件大小估计一个微信自动审核的时间,审核结束前返回将会导致语音无法播放,这个估计有待验证 - f_size = os.fstat(f.fileno()).st_size - time.sleep(1.0 + 2 * f_size / 1024 / 1024) - # todo check media_id - except WeChatClientException as e: - logger.error("[wechatmp] upload voice failed: {}".format(e)) - return - media_id = response["media_id"] - logger.info("[wechatmp] voice uploaded, receiver {}, media_id {}".format(receiver, media_id)) - self.cache_dict[receiver] = ("voice", media_id) + voice_file_path = reply.content + duration, files = split_audio(voice_file_path, 60 * 1000) + if len(files) > 1: + logger.info("[wechatmp] voice too long {}s > 60s , split into {} parts".format(duration / 1000.0, len(files))) + + for path in files: + # support: <2M, <60s, mp3/wma/wav/amr + try: + with open(path, "rb") as f: + response = self.client.material.add("voice", f) + logger.debug("[wechatmp] upload voice response: {}".format(response)) + f_size = os.fstat(f.fileno()).st_size + time.sleep(1.0 + 2 * f_size / 1024 / 1024) + # todo check media_id + except WeChatClientException as e: + logger.error("[wechatmp] upload voice failed: {}".format(e)) + return + media_id = response["media_id"] + logger.info("[wechatmp] voice uploaded, receiver {}, media_id {}".format(receiver, media_id)) + self.cache_dict[receiver].append(("voice", media_id)) elif reply.type == ReplyType.IMAGE_URL: # 从网络下载图片 img_url = reply.content @@ -119,7 +124,7 @@ def send(self, reply: Reply, context: Context): return media_id = response["media_id"] logger.info("[wechatmp] image uploaded, receiver {}, media_id {}".format(receiver, media_id)) - self.cache_dict[receiver] = ("image", media_id) + self.cache_dict[receiver].append(("image", media_id)) elif reply.type == ReplyType.IMAGE: # 从文件读取图片 image_storage = reply.content image_storage.seek(0) @@ -134,7 +139,7 @@ def send(self, reply: Reply, context: Context): return media_id = response["media_id"] logger.info("[wechatmp] image uploaded, receiver {}, media_id {}".format(receiver, media_id)) - self.cache_dict[receiver] = ("image", media_id) + self.cache_dict[receiver].append(("image", media_id)) else: if reply.type == ReplyType.TEXT or reply.type == ReplyType.INFO or reply.type == ReplyType.ERROR: reply_text = reply.content