選択できるのは25トピックまでです。 トピックは、先頭が英数字で、英数字とダッシュ('-')を使用した35文字以内のものにしてください。

130 行
4.9KB

  1. #!/usr/bin/env python
  2. # -*- coding=utf-8 -*-
  3. import os
  4. import web
  5. from wechatpy.enterprise import WeChatClient, create_reply, parse_message
  6. from wechatpy.enterprise.crypto import WeChatCrypto
  7. from wechatpy.enterprise.exceptions import InvalidCorpIdException
  8. from wechatpy.exceptions import InvalidSignatureException, WeChatClientException
  9. from bridge.context import Context
  10. from bridge.reply import Reply, ReplyType
  11. from channel.chat_channel import ChatChannel
  12. from channel.wechatcom.wechatcom_message import WechatComMessage
  13. from common.log import logger
  14. from common.singleton import singleton
  15. from config import conf
  16. from voice.audio_convert import any_to_amr
  17. @singleton
  18. class WechatComChannel(ChatChannel):
  19. NOT_SUPPORT_REPLYTYPE = [ReplyType.IMAGE]
  20. def __init__(self):
  21. super().__init__()
  22. self.corp_id = conf().get("wechatcom_corp_id")
  23. self.secret = conf().get("wechatcom_secret")
  24. self.agent_id = conf().get("wechatcom_agent_id")
  25. self.token = conf().get("wechatcom_token")
  26. self.aes_key = conf().get("wechatcom_aes_key")
  27. print(self.corp_id, self.secret, self.agent_id, self.token, self.aes_key)
  28. logger.info(
  29. "[wechatcom] init: corp_id: {}, secret: {}, agent_id: {}, token: {}, aes_key: {}".format(
  30. self.corp_id, self.secret, self.agent_id, self.token, self.aes_key
  31. )
  32. )
  33. self.crypto = WeChatCrypto(self.token, self.aes_key, self.corp_id)
  34. self.client = WeChatClient(self.corp_id, self.secret) # todo: 这里可能有线程安全问题
  35. def startup(self):
  36. # start message listener
  37. urls = ("/wxcom", "channel.wechatcom.wechatcom_channel.Query")
  38. app = web.application(urls, globals(), autoreload=False)
  39. port = conf().get("wechatcom_port", 8080)
  40. web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
  41. def send(self, reply: Reply, context: Context):
  42. receiver = context["receiver"]
  43. if reply.type in [ReplyType.TEXT, ReplyType.ERROR, ReplyType.INFO]:
  44. self.client.message.send_text(self.agent_id, receiver, reply.content)
  45. logger.info("[wechatcom] sendMsg={}, receiver={}".format(reply, receiver))
  46. elif reply.type == ReplyType.VOICE:
  47. try:
  48. file_path = reply.content
  49. amr_file = os.path.splitext(file_path)[0] + ".amr"
  50. any_to_amr(file_path, amr_file)
  51. response = self.client.media.upload("voice", open(amr_file, "rb"))
  52. logger.debug("[wechatcom] upload voice response: {}".format(response))
  53. except WeChatClientException as e:
  54. logger.error("[wechatcom] upload voice failed: {}".format(e))
  55. return
  56. try:
  57. os.remove(file_path)
  58. if amr_file != file_path:
  59. os.remove(amr_file)
  60. except Exception:
  61. pass
  62. self.client.message.send_voice(
  63. self.agent_id, receiver, response["media_id"]
  64. )
  65. logger.info(
  66. "[wechatcom] sendVoice={}, receiver={}".format(reply.content, receiver)
  67. )
  68. class Query:
  69. def GET(self):
  70. channel = WechatComChannel()
  71. params = web.input()
  72. signature = params.msg_signature
  73. timestamp = params.timestamp
  74. nonce = params.nonce
  75. echostr = params.echostr
  76. print(params)
  77. try:
  78. echostr = channel.crypto.check_signature(
  79. signature, timestamp, nonce, echostr
  80. )
  81. except InvalidSignatureException:
  82. raise web.Forbidden()
  83. return echostr
  84. def POST(self):
  85. channel = WechatComChannel()
  86. params = web.input()
  87. signature = params.msg_signature
  88. timestamp = params.timestamp
  89. nonce = params.nonce
  90. try:
  91. message = channel.crypto.decrypt_message(
  92. web.data(), signature, timestamp, nonce
  93. )
  94. except (InvalidSignatureException, InvalidCorpIdException):
  95. raise web.Forbidden()
  96. print(message)
  97. msg = parse_message(message)
  98. print(msg)
  99. if msg.type == "event":
  100. if msg.event == "subscribe":
  101. reply = create_reply("感谢关注", msg).render()
  102. res = channel.crypto.encrypt_message(reply, nonce, timestamp)
  103. return res
  104. else:
  105. try:
  106. wechatcom_msg = WechatComMessage(msg, client=channel.client)
  107. except NotImplementedError as e:
  108. logger.debug("[wechatcom] " + str(e))
  109. return "success"
  110. context = channel._compose_context(
  111. wechatcom_msg.ctype,
  112. wechatcom_msg.content,
  113. isgroup=False,
  114. msg=wechatcom_msg,
  115. )
  116. if context:
  117. channel.produce(context)
  118. return "success"