您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

dingtalk_channel.py 4.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. """
  2. 钉钉通道接入
  3. @author huiwen
  4. @Date 2023/11/28
  5. """
  6. # -*- coding=utf-8 -*-
  7. from channel.dingtalk.dingtalk_message import DingTalkMessage
  8. from bridge.context import Context
  9. from bridge.reply import Reply
  10. from common.log import logger
  11. from common.singleton import singleton
  12. from config import conf
  13. from common.expired_dict import ExpiredDict
  14. from bridge.context import ContextType
  15. from channel.chat_channel import ChatChannel
  16. import logging
  17. from dingtalk_stream import AckMessage
  18. import dingtalk_stream
  19. @singleton
  20. class DingTalkChanel(ChatChannel, dingtalk_stream.ChatbotHandler):
  21. dingtalk_client_id = conf().get('dingtalk_client_id')
  22. dingtalk_client_secret = conf().get('dingtalk_client_secret')
  23. def setup_logger(self):
  24. logger = logging.getLogger()
  25. handler = logging.StreamHandler()
  26. handler.setFormatter(
  27. logging.Formatter('%(asctime)s %(name)-8s %(levelname)-8s %(message)s [%(filename)s:%(lineno)d]'))
  28. logger.addHandler(handler)
  29. logger.setLevel(logging.INFO)
  30. return logger
  31. def __init__(self):
  32. super().__init__()
  33. super(dingtalk_stream.ChatbotHandler, self).__init__()
  34. self.logger = self.setup_logger()
  35. # 历史消息id暂存,用于幂等控制
  36. self.receivedMsgs = ExpiredDict(60 * 60 * 7.1)
  37. logger.info("[dingtalk] client_id={}, client_secret={} ".format(
  38. self.dingtalk_client_id, self.dingtalk_client_secret))
  39. # 无需群校验和前缀
  40. conf()["group_name_white_list"] = ["ALL_GROUP"]
  41. def startup(self):
  42. credential = dingtalk_stream.Credential(self.dingtalk_client_id, self.dingtalk_client_secret)
  43. client = dingtalk_stream.DingTalkStreamClient(credential)
  44. client.register_callback_handler(dingtalk_stream.chatbot.ChatbotMessage.TOPIC, self)
  45. client.start_forever()
  46. def handle_single(self, cmsg: DingTalkMessage):
  47. # 处理单聊消息
  48. if cmsg.ctype == ContextType.VOICE:
  49. logger.debug("[dingtalk]receive voice msg: {}".format(cmsg.content))
  50. elif cmsg.ctype == ContextType.IMAGE:
  51. logger.debug("[dingtalk]receive image msg: {}".format(cmsg.content))
  52. elif cmsg.ctype == ContextType.PATPAT:
  53. logger.debug("[dingtalk]receive patpat msg: {}".format(cmsg.content))
  54. elif cmsg.ctype == ContextType.TEXT:
  55. expression = cmsg.my_msg
  56. cmsg.content = conf()["single_chat_prefix"][0] + cmsg.content
  57. context = self._compose_context(cmsg.ctype, cmsg.content, isgroup=False, msg=cmsg)
  58. if context:
  59. self.produce(context)
  60. def handle_group(self, cmsg: DingTalkMessage):
  61. # 处理群聊消息
  62. if cmsg.ctype == ContextType.VOICE:
  63. logger.debug("[dingtalk]receive voice msg: {}".format(cmsg.content))
  64. elif cmsg.ctype == ContextType.IMAGE:
  65. logger.debug("[dingtalk]receive image msg: {}".format(cmsg.content))
  66. elif cmsg.ctype == ContextType.PATPAT:
  67. logger.debug("[dingtalk]receive patpat msg: {}".format(cmsg.content))
  68. elif cmsg.ctype == ContextType.TEXT:
  69. expression = cmsg.my_msg
  70. cmsg.content = conf()["group_chat_prefix"][0] + cmsg.content
  71. context = self._compose_context(cmsg.ctype, cmsg.content, isgroup=True, msg=cmsg)
  72. context['no_need_at'] = True
  73. if context:
  74. self.produce(context)
  75. async def process(self, callback: dingtalk_stream.CallbackMessage):
  76. try:
  77. incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
  78. dingtalk_msg = DingTalkMessage(incoming_message)
  79. if incoming_message.conversation_type == '1':
  80. self.handle_single(dingtalk_msg)
  81. else:
  82. self.handle_group(dingtalk_msg)
  83. return AckMessage.STATUS_OK, 'OK'
  84. except Exception as e:
  85. logger.error(e)
  86. return self.FAILED_MSG
  87. def send(self, reply: Reply, context: Context):
  88. incoming_message = context.kwargs['msg'].incoming_message
  89. self.reply_text(reply.content, incoming_message)