You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

155 lines
5.4KB

  1. # encoding:utf-8
  2. """
  3. wechat channel
  4. """
  5. import itchat
  6. import json
  7. from itchat.content import *
  8. from channel.channel import Channel
  9. from concurrent.futures import ThreadPoolExecutor
  10. from common.log import logger
  11. from config import conf
  12. import requests
  13. import io
  14. thead_pool = ThreadPoolExecutor(max_workers=8)
  15. @itchat.msg_register(TEXT)
  16. def handler_single_msg(msg):
  17. WechatChannel().handle(msg)
  18. return None
  19. @itchat.msg_register(TEXT, isGroupChat=True)
  20. def handler_group_msg(msg):
  21. WechatChannel().handle_group(msg)
  22. return None
  23. class WechatChannel(Channel):
  24. def __init__(self):
  25. pass
  26. def startup(self):
  27. # login by scan QRCode
  28. itchat.auto_login(enableCmdQR=2)
  29. # start message listener
  30. itchat.run()
  31. def handle(self, msg):
  32. logger.info("[WX]receive msg: " + json.dumps(msg, ensure_ascii=False))
  33. from_user_id = msg['FromUserName']
  34. to_user_id = msg['ToUserName'] # 接收人id
  35. other_user_id = msg['User']['UserName'] # 对手方id
  36. content = msg['Text']
  37. match_prefix = self.check_prefix(content, conf().get('single_chat_prefix'))
  38. if from_user_id == other_user_id and match_prefix:
  39. # 好友向自己发送消息
  40. str_list = content.split(match_prefix, 1)
  41. if len(str_list) == 2:
  42. content = str_list[1].strip()
  43. img_match_prefix = self.check_prefix(content, conf().get('image_create_prefix'))
  44. if img_match_prefix:
  45. content = content.split(img_match_prefix, 1)[1].strip()
  46. thead_pool.submit(self._do_send_img, content, from_user_id)
  47. else:
  48. thead_pool.submit(self._do_send, content, from_user_id)
  49. elif to_user_id == other_user_id and match_prefix:
  50. # 自己给好友发送消息
  51. str_list = content.split(match_prefix, 1)
  52. if len(str_list) == 2:
  53. content = str_list[1].strip()
  54. img_match_prefix = self.check_prefix(content, conf().get('image_create_prefix'))
  55. if img_match_prefix:
  56. content = content.split(img_match_prefix, 1)[1].strip()
  57. thead_pool.submit(self._do_send_img, content, to_user_id)
  58. else:
  59. thead_pool.submit(self._do_send, content, to_user_id)
  60. def handle_group(self, msg):
  61. logger.info("[WX]receive group msg: " + json.dumps(msg, ensure_ascii=False))
  62. group_name = msg['User'].get('NickName', None)
  63. group_id = msg['User'].get('UserName', None)
  64. if not group_name:
  65. return ""
  66. origin_content = msg['Content']
  67. content = msg['Content']
  68. content_list = content.split(' ', 1)
  69. context_special_list = content.split('\u2005', 1)
  70. if len(context_special_list) == 2:
  71. content = context_special_list[1]
  72. elif len(content_list) == 2:
  73. content = content_list[1]
  74. config = conf()
  75. match_prefix = msg['IsAt'] or self.check_prefix(origin_content, config.get('group_chat_prefix'))
  76. if group_name in config.get('group_name_white_list') and match_prefix:
  77. img_match_prefix = self.check_prefix(content, conf().get('image_create_prefix'))
  78. if img_match_prefix:
  79. content = content.split(img_match_prefix, 1)[1].strip()
  80. thead_pool.submit(self._do_send_img, content, group_id)
  81. else:
  82. thead_pool.submit(self._do_send_group, content, msg)
  83. def send(self, msg, receiver):
  84. logger.info('[WX] sendMsg={}, receiver={}'.format(msg, receiver))
  85. itchat.send(msg, toUserName=receiver)
  86. def _do_send(self, query, reply_user_id):
  87. try:
  88. if not query:
  89. return
  90. context = dict()
  91. context['from_user_id'] = reply_user_id
  92. reply_text = super().build_reply_content(query, context).strip()
  93. if reply_text:
  94. self.send(conf().get("single_chat_reply_prefix") + reply_text, reply_user_id)
  95. except Exception as e:
  96. logger.exception(e)
  97. def _do_send_img(self, query, reply_user_id):
  98. try:
  99. if not query:
  100. return
  101. context = dict()
  102. context['type'] = 'IMAGE_CREATE'
  103. img_url = super().build_reply_content(query, context)
  104. if not img_url:
  105. return
  106. # 图片下载
  107. pic_res = requests.get(img_url, stream=True)
  108. image_storage = io.BytesIO()
  109. for block in pic_res.iter_content(1024):
  110. image_storage.write(block)
  111. image_storage.seek(0)
  112. # 图片发送
  113. logger.info('[WX] sendImage, receiver={}'.format(reply_user_id))
  114. itchat.send_image(image_storage, reply_user_id)
  115. except Exception as e:
  116. logger.exception(e)
  117. def _do_send_group(self, query, msg):
  118. if not query:
  119. return
  120. context = dict()
  121. context['from_user_id'] = msg['ActualUserName']
  122. reply_text = super().build_reply_content(query, context)
  123. reply_text = '@' + msg['ActualNickName'] + ' ' + reply_text.strip()
  124. if reply_text:
  125. self.send(reply_text, msg['User']['UserName'])
  126. def check_prefix(self, content, prefix_list):
  127. for prefix in prefix_list:
  128. if content.lower().startswith(prefix):
  129. return prefix
  130. return None