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.

106 lines
4.0KB

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