Browse Source

feat(wechatcom): add support for sending voice messages

lanvent 3 years ago
parent
commit
ab83dacb76
3 changed files with 49 additions and 6 deletions
  1. 1 0
      .pre-commit-config.yaml
  2. 30 6
      channel/wechatcom/wechatcom_channel.py
  3. 18 0
      voice/audio_convert.py

+ 1 - 0
.pre-commit-config.yaml

@@ -18,6 +18,7 @@ repos:
     hooks:
       - id: isort
         exclude: '(\/|^)lib\/'
+        args: [ -l, '88']
   - repo: https://github.com/psf/black
     rev: 23.3.0
     hooks:

+ 30 - 6
channel/wechatcom/wechatcom_channel.py

@@ -1,10 +1,12 @@
 #!/usr/bin/env python
 # -*- coding=utf-8 -*-
+import os
+
 import web
 from wechatpy.enterprise import WeChatClient, create_reply, parse_message
 from wechatpy.enterprise.crypto import WeChatCrypto
 from wechatpy.enterprise.exceptions import InvalidCorpIdException
-from wechatpy.exceptions import InvalidSignatureException
+from wechatpy.exceptions import InvalidSignatureException, WeChatClientException
 
 from bridge.context import Context
 from bridge.reply import Reply, ReplyType
@@ -13,11 +15,12 @@ from channel.wechatcom.wechatcom_message import WechatComMessage
 from common.log import logger
 from common.singleton import singleton
 from config import conf
+from voice.audio_convert import any_to_amr
 
 
 @singleton
 class WechatComChannel(ChatChannel):
-    NOT_SUPPORT_REPLYTYPE = [ReplyType.IMAGE, ReplyType.VOICE]
+    NOT_SUPPORT_REPLYTYPE = [ReplyType.IMAGE]
 
     def __init__(self):
         super().__init__()
@@ -43,11 +46,32 @@ class WechatComChannel(ChatChannel):
         web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
 
     def send(self, reply: Reply, context: Context):
-        print("send reply: ", reply.content, context["receiver"])
         receiver = context["receiver"]
-        reply_text = reply.content
-        self.client.message.send_text(self.agent_id, receiver, reply_text)
-        logger.info("[send] Do send to {}: {}".format(receiver, reply_text))
+        if reply.type in [ReplyType.TEXT, ReplyType.ERROR, ReplyType.INFO]:
+            self.client.message.send_text(self.agent_id, receiver, reply.content)
+            logger.info("[wechatcom] sendMsg={}, receiver={}".format(reply, receiver))
+        elif reply.type == ReplyType.VOICE:
+            try:
+                file_path = reply.content
+                amr_file = os.path.splitext(file_path)[0] + ".amr"
+                any_to_amr(file_path, amr_file)
+                response = self.client.media.upload("voice", open(amr_file, "rb"))
+                logger.debug("[wechatcom] upload voice response: {}".format(response))
+            except WeChatClientException as e:
+                logger.error("[wechatcom] upload voice failed: {}".format(e))
+                return
+            try:
+                os.remove(file_path)
+                if amr_file != file_path:
+                    os.remove(amr_file)
+            except Exception:
+                pass
+            self.client.message.send_voice(
+                self.agent_id, receiver, response["media_id"]
+            )
+            logger.info(
+                "[wechatcom] sendVoice={}, receiver={}".format(reply.content, receiver)
+            )
 
 
 class Query:

+ 18 - 0
voice/audio_convert.py

@@ -69,6 +69,24 @@ def any_to_sil(any_path, sil_path):
     raise NotImplementedError("Not support file type: {}".format(any_path))
 
 
+def any_to_amr(any_path, amr_path):
+    """
+    把任意格式转成amr文件
+    """
+    if any_path.endswith(".amr"):
+        shutil.copy2(any_path, amr_path)
+        return
+    if (
+        any_path.endswith(".sil")
+        or any_path.endswith(".silk")
+        or any_path.endswith(".slk")
+    ):
+        raise NotImplementedError("Not support file type: {}".format(any_path))
+    audio = AudioSegment.from_file(any_path)
+    audio = audio.set_frame_rate(8000)  # only support 8000
+    audio.export(amr_path, format="amr")
+
+
 def mp3_to_wav(mp3_path, wav_path):
     """
     把mp3格式转成pcm文件