Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

101 linhas
4.0KB

  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)