Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

171 lines
6.2KB

  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. thread_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.debug("[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 "」\n- - - - - - - - - - - - - - -" in content:
  39. logger.debug("[WX]reference query skipped")
  40. return
  41. if from_user_id == other_user_id and match_prefix is not None:
  42. # 好友向自己发送消息
  43. if match_prefix != '':
  44. str_list = content.split(match_prefix, 1)
  45. if len(str_list) == 2:
  46. content = str_list[1].strip()
  47. img_match_prefix = self.check_prefix(content, conf().get('image_create_prefix'))
  48. if img_match_prefix:
  49. content = content.split(img_match_prefix, 1)[1].strip()
  50. thread_pool.submit(self._do_send_img, content, from_user_id)
  51. else:
  52. thread_pool.submit(self._do_send, content, from_user_id)
  53. elif to_user_id == other_user_id and match_prefix:
  54. # 自己给好友发送消息
  55. str_list = content.split(match_prefix, 1)
  56. if len(str_list) == 2:
  57. content = str_list[1].strip()
  58. img_match_prefix = self.check_prefix(content, conf().get('image_create_prefix'))
  59. if img_match_prefix:
  60. content = content.split(img_match_prefix, 1)[1].strip()
  61. thread_pool.submit(self._do_send_img, content, to_user_id)
  62. else:
  63. thread_pool.submit(self._do_send, content, to_user_id)
  64. def handle_group(self, msg):
  65. logger.debug("[WX]receive group msg: " + json.dumps(msg, ensure_ascii=False))
  66. group_name = msg['User'].get('NickName', None)
  67. group_id = msg['User'].get('UserName', None)
  68. if not group_name:
  69. return ""
  70. origin_content = msg['Content']
  71. content = msg['Content']
  72. content_list = content.split(' ', 1)
  73. context_special_list = content.split('\u2005', 1)
  74. if len(context_special_list) == 2:
  75. content = context_special_list[1]
  76. elif len(content_list) == 2:
  77. content = content_list[1]
  78. if "」\n- - - - - - - - - - - - - - -" in content:
  79. logger.debug("[WX]reference query skipped")
  80. return ""
  81. config = conf()
  82. match_prefix = (msg['IsAt'] and not config.get("group_at_off", False)) or self.check_prefix(origin_content, config.get('group_chat_prefix')) \
  83. or self.check_contain(origin_content, config.get('group_chat_keyword'))
  84. if ('ALL_GROUP' in config.get('group_name_white_list') or group_name in config.get('group_name_white_list') or self.check_contain(group_name, config.get('group_name_keyword_white_list'))) and match_prefix:
  85. img_match_prefix = self.check_prefix(content, conf().get('image_create_prefix'))
  86. if img_match_prefix:
  87. content = content.split(img_match_prefix, 1)[1].strip()
  88. thread_pool.submit(self._do_send_img, content, group_id)
  89. else:
  90. thread_pool.submit(self._do_send_group, content, msg)
  91. def send(self, msg, receiver):
  92. logger.info('[WX] sendMsg={}, receiver={}'.format(msg, receiver))
  93. itchat.send(msg, toUserName=receiver)
  94. def _do_send(self, query, reply_user_id):
  95. try:
  96. if not query:
  97. return
  98. context = dict()
  99. context['from_user_id'] = reply_user_id
  100. reply_text = super().build_reply_content(query, context)
  101. if reply_text:
  102. self.send(conf().get("single_chat_reply_prefix") + reply_text, reply_user_id)
  103. except Exception as e:
  104. logger.exception(e)
  105. def _do_send_img(self, query, reply_user_id):
  106. try:
  107. if not query:
  108. return
  109. context = dict()
  110. context['type'] = 'IMAGE_CREATE'
  111. img_url = super().build_reply_content(query, context)
  112. if not img_url:
  113. return
  114. # 图片下载
  115. pic_res = requests.get(img_url, stream=True)
  116. image_storage = io.BytesIO()
  117. for block in pic_res.iter_content(1024):
  118. image_storage.write(block)
  119. image_storage.seek(0)
  120. # 图片发送
  121. logger.info('[WX] sendImage, receiver={}'.format(reply_user_id))
  122. itchat.send_image(image_storage, reply_user_id)
  123. except Exception as e:
  124. logger.exception(e)
  125. def _do_send_group(self, query, msg):
  126. if not query:
  127. return
  128. context = dict()
  129. context['from_user_id'] = msg['ActualUserName']
  130. reply_text = super().build_reply_content(query, context)
  131. if reply_text:
  132. reply_text = '@' + msg['ActualNickName'] + ' ' + reply_text.strip()
  133. self.send(conf().get("group_chat_reply_prefix", "") + reply_text, msg['User']['UserName'])
  134. def check_prefix(self, content, prefix_list):
  135. for prefix in prefix_list:
  136. if content.startswith(prefix):
  137. return prefix
  138. return None
  139. def check_contain(self, content, keyword_list):
  140. if not keyword_list:
  141. return None
  142. for ky in keyword_list:
  143. if content.find(ky) != -1:
  144. return True
  145. return None