Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

119 lines
5.1KB

  1. # -*- coding: utf-8 -*-
  2. import io
  3. import imghdr
  4. import requests
  5. from bridge.context import *
  6. from bridge.reply import *
  7. from channel.chat_channel import ChatChannel
  8. from channel.wechatmp.wechatmp_client import WechatMPClient
  9. from channel.wechatmp.common import *
  10. from common.log import logger
  11. from common.singleton import singleton
  12. from config import conf
  13. import web
  14. # If using SSL, uncomment the following lines, and modify the certificate path.
  15. # from cheroot.server import HTTPServer
  16. # from cheroot.ssl.builtin import BuiltinSSLAdapter
  17. # HTTPServer.ssl_adapter = BuiltinSSLAdapter(
  18. # certificate='/ssl/cert.pem',
  19. # private_key='/ssl/cert.key')
  20. @singleton
  21. class WechatMPChannel(ChatChannel):
  22. def __init__(self, passive_reply=True):
  23. super().__init__()
  24. self.passive_reply = passive_reply
  25. self.flag = 0
  26. self.client = WechatMPClient()
  27. if self.passive_reply:
  28. self.NOT_SUPPORT_REPLYTYPE = [ReplyType.IMAGE, ReplyType.VOICE]
  29. # Cache the reply to the user's first message
  30. self.cache_dict = dict()
  31. # Record whether the current message is being processed
  32. self.running = set()
  33. # Count the request from wechat official server by message_id
  34. self.request_cnt = dict()
  35. else:
  36. self.NOT_SUPPORT_REPLYTYPE = []
  37. def startup(self):
  38. if self.passive_reply:
  39. urls = ("/wx", "channel.wechatmp.passive_reply.Query")
  40. else:
  41. urls = ("/wx", "channel.wechatmp.active_reply.Query")
  42. app = web.application(urls, globals(), autoreload=False)
  43. port = conf().get("wechatmp_port", 8080)
  44. web.httpserver.runsimple(app.wsgifunc(), ("0.0.0.0", port))
  45. def send(self, reply: Reply, context: Context):
  46. receiver = context["receiver"]
  47. if self.passive_reply:
  48. logger.info("[wechatmp] reply to {} cached:\n{}".format(receiver, reply))
  49. self.cache_dict[receiver] = reply.content
  50. else:
  51. if reply.type == ReplyType.TEXT or reply.type == ReplyType.INFO or reply.type == ReplyType.ERROR:
  52. reply_text = reply.content
  53. self.client.send_text(receiver, reply_text)
  54. logger.info("[wechatmp] Do send to {}: {}".format(receiver, reply_text))
  55. elif reply.type == ReplyType.VOICE:
  56. voice_file_path = reply.content
  57. logger.info("[wechatmp] voice file path {}".format(voice_file_path))
  58. with open(voice_file_path, 'rb') as f:
  59. filename = receiver + "-" + context["msg"].msg_id + ".mp3"
  60. media_id = self.client.upload_media("voice", (filename, f, "audio/mpeg"))
  61. self.client.send_voice(receiver, media_id)
  62. logger.info("[wechatmp] Do send voice to {}".format(receiver))
  63. elif reply.type == ReplyType.IMAGE_URL: # 从网络下载图片
  64. img_url = reply.content
  65. pic_res = requests.get(img_url, stream=True)
  66. print(pic_res.headers)
  67. image_storage = io.BytesIO()
  68. for block in pic_res.iter_content(1024):
  69. image_storage.write(block)
  70. image_storage.seek(0)
  71. image_type = imghdr.what(image_storage)
  72. filename = receiver + "-" + context["msg"].msg_id + "." + image_type
  73. content_type = "image/" + image_type
  74. # content_type = pic_res.headers.get('content-type')
  75. media_id = self.client.upload_media("image", (filename, image_storage, content_type))
  76. self.client.send_image(receiver, media_id)
  77. logger.info("[wechatmp] sendImage url={}, receiver={}".format(img_url, receiver))
  78. elif reply.type == ReplyType.IMAGE: # 从文件读取图片
  79. image_storage = reply.content
  80. image_storage.seek(0)
  81. image_type = imghdr.what(image_storage)
  82. filename = receiver + "-" + context["msg"].msg_id + "." + image_type
  83. content_type = "image/" + image_type
  84. media_id = self.client.upload_media("image", (filename, image_storage, content_type))
  85. self.client.send_image(receiver, media_id)
  86. logger.info("[wechatmp] sendImage, receiver={}".format(receiver))
  87. return
  88. def _success_callback(self, session_id, context, **kwargs): # 线程异常结束时的回调函数
  89. logger.debug(
  90. "[wechatmp] Success to generate reply, msgId={}".format(
  91. context["msg"].msg_id
  92. )
  93. )
  94. if self.passive_reply:
  95. self.running.remove(session_id)
  96. def _fail_callback(self, session_id, exception, context, **kwargs): # 线程异常结束时的回调函数
  97. logger.exception(
  98. "[wechatmp] Fail to generate reply to user, msgId={}, exception={}".format(
  99. context["msg"].msg_id, exception
  100. )
  101. )
  102. if self.passive_reply:
  103. assert session_id not in self.cache_dict
  104. self.running.remove(session_id)