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.

107 lines
4.3KB

  1. import logging, traceback, sys, threading
  2. try:
  3. import Queue
  4. except ImportError:
  5. import queue as Queue # type: ignore
  6. from ..log import set_logging
  7. from ..utils import test_connect
  8. from ..storage import templates
  9. logger = logging.getLogger('itchat')
  10. def load_register(core):
  11. core.auto_login = auto_login
  12. core.configured_reply = configured_reply
  13. core.msg_register = msg_register
  14. core.run = run
  15. async def auto_login(self, EventScanPayload=None,ScanStatus=None,event_stream=None,
  16. hotReload=True, statusStorageDir='itchat.pkl',
  17. enableCmdQR=False, picDir=None, qrCallback=None,
  18. loginCallback=None, exitCallback=None):
  19. if not test_connect():
  20. logger.info("You can't get access to internet or wechat domain, so exit.")
  21. sys.exit()
  22. self.useHotReload = hotReload
  23. self.hotReloadDir = statusStorageDir
  24. if hotReload:
  25. if await self.load_login_status(statusStorageDir,
  26. loginCallback=loginCallback, exitCallback=exitCallback):
  27. return
  28. await self.login(enableCmdQR=enableCmdQR, picDir=picDir, qrCallback=qrCallback, EventScanPayload=EventScanPayload, ScanStatus=ScanStatus, event_stream=event_stream,
  29. loginCallback=loginCallback, exitCallback=exitCallback)
  30. await self.dump_login_status(statusStorageDir)
  31. else:
  32. await self.login(enableCmdQR=enableCmdQR, picDir=picDir, qrCallback=qrCallback, EventScanPayload=EventScanPayload, ScanStatus=ScanStatus, event_stream=event_stream,
  33. loginCallback=loginCallback, exitCallback=exitCallback)
  34. async def configured_reply(self, event_stream, payload, message_container):
  35. ''' determine the type of message and reply if its method is defined
  36. however, I use a strange way to determine whether a msg is from massive platform
  37. I haven't found a better solution here
  38. The main problem I'm worrying about is the mismatching of new friends added on phone
  39. If you have any good idea, pleeeease report an issue. I will be more than grateful.
  40. '''
  41. try:
  42. msg = self.msgList.get(timeout=1)
  43. if 'MsgId' in msg.keys():
  44. message_container[msg['MsgId']] = msg
  45. except Queue.Empty:
  46. pass
  47. else:
  48. if isinstance(msg['User'], templates.User):
  49. replyFn = self.functionDict['FriendChat'].get(msg['Type'])
  50. elif isinstance(msg['User'], templates.MassivePlatform):
  51. replyFn = self.functionDict['MpChat'].get(msg['Type'])
  52. elif isinstance(msg['User'], templates.Chatroom):
  53. replyFn = self.functionDict['GroupChat'].get(msg['Type'])
  54. if replyFn is None:
  55. r = None
  56. else:
  57. try:
  58. r = await replyFn(msg)
  59. if r is not None:
  60. await self.send(r, msg.get('FromUserName'))
  61. except:
  62. logger.warning(traceback.format_exc())
  63. def msg_register(self, msgType, isFriendChat=False, isGroupChat=False, isMpChat=False):
  64. ''' a decorator constructor
  65. return a specific decorator based on information given '''
  66. if not (isinstance(msgType, list) or isinstance(msgType, tuple)):
  67. msgType = [msgType]
  68. def _msg_register(fn):
  69. for _msgType in msgType:
  70. if isFriendChat:
  71. self.functionDict['FriendChat'][_msgType] = fn
  72. if isGroupChat:
  73. self.functionDict['GroupChat'][_msgType] = fn
  74. if isMpChat:
  75. self.functionDict['MpChat'][_msgType] = fn
  76. if not any((isFriendChat, isGroupChat, isMpChat)):
  77. self.functionDict['FriendChat'][_msgType] = fn
  78. return fn
  79. return _msg_register
  80. async def run(self, debug=False, blockThread=True):
  81. logger.info('Start auto replying.')
  82. if debug:
  83. set_logging(loggingLevel=logging.DEBUG)
  84. async def reply_fn():
  85. try:
  86. while self.alive:
  87. await self.configured_reply()
  88. except KeyboardInterrupt:
  89. if self.useHotReload:
  90. await self.dump_login_status()
  91. self.alive = False
  92. logger.debug('itchat received an ^C and exit.')
  93. logger.info('Bye~')
  94. if blockThread:
  95. await reply_fn()
  96. else:
  97. replyThread = threading.Thread(target=reply_fn)
  98. replyThread.setDaemon(True)
  99. replyThread.start()