dingtalk_channel.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. """
  2. 钉钉通道接入
  3. @author huiwen
  4. @Date 2023/11/28
  5. """
  6. # -*- coding=utf-8 -*-
  7. import uuid
  8. import requests
  9. import web
  10. from channel.dingtalk.dingtalk_message import DingTalkMessage
  11. from bridge.context import Context
  12. from bridge.reply import Reply, ReplyType
  13. from common.log import logger
  14. from common.singleton import singleton
  15. from config import conf
  16. from common.expired_dict import ExpiredDict
  17. from bridge.context import ContextType
  18. from channel.chat_channel import ChatChannel, check_prefix
  19. from common import utils
  20. import json
  21. import os
  22. import argparse
  23. import logging
  24. from dingtalk_stream import AckMessage
  25. import dingtalk_stream
  26. @singleton
  27. class DingTalkChanel(ChatChannel,dingtalk_stream.ChatbotHandler):
  28. dingtalk_client_id = conf().get('dingtalk_client_id')
  29. dingtalk_client_secret = conf().get('dingtalk_client_secret')
  30. def setup_logger(self):
  31. logger = logging.getLogger()
  32. handler = logging.StreamHandler()
  33. handler.setFormatter(
  34. logging.Formatter('%(asctime)s %(name)-8s %(levelname)-8s %(message)s [%(filename)s:%(lineno)d]'))
  35. logger.addHandler(handler)
  36. logger.setLevel(logging.INFO)
  37. return logger
  38. def __init__(self):
  39. super().__init__()
  40. super(dingtalk_stream.ChatbotHandler, self).__init__()
  41. self.logger = self.setup_logger()
  42. # 历史消息id暂存,用于幂等控制
  43. self.receivedMsgs = ExpiredDict(60 * 60 * 7.1)
  44. logger.info("[dingtalk] client_id={}, client_secret={} ".format(
  45. self.dingtalk_client_id, self.dingtalk_client_secret))
  46. # 无需群校验和前缀
  47. conf()["group_name_white_list"] = ["ALL_GROUP"]
  48. def startup(self):
  49. credential = dingtalk_stream.Credential( self.dingtalk_client_id, self.dingtalk_client_secret)
  50. client = dingtalk_stream.DingTalkStreamClient(credential)
  51. client.register_callback_handler(dingtalk_stream.chatbot.ChatbotMessage.TOPIC,self)
  52. client.start_forever()
  53. def handle_single(self, cmsg:DingTalkMessage):
  54. # 处理单聊消息
  55. #
  56. if cmsg.ctype == ContextType.VOICE:
  57. logger.debug("[dingtalk]receive voice msg: {}".format(cmsg.content))
  58. elif cmsg.ctype == ContextType.IMAGE:
  59. logger.debug("[dingtalk]receive image msg: {}".format(cmsg.content))
  60. elif cmsg.ctype == ContextType.PATPAT:
  61. logger.debug("[dingtalk]receive patpat msg: {}".format(cmsg.content))
  62. elif cmsg.ctype == ContextType.TEXT:
  63. expression = cmsg.my_msg
  64. cmsg.content = conf()["single_chat_prefix"][0] + cmsg.content
  65. context = self._compose_context(cmsg.ctype, cmsg.content, isgroup=False, msg=cmsg)
  66. if context:
  67. self.produce(context)
  68. def handle_group(self, cmsg:DingTalkMessage):
  69. # 处理群聊消息
  70. #
  71. if cmsg.ctype == ContextType.VOICE:
  72. logger.debug("[dingtalk]receive voice msg: {}".format(cmsg.content))
  73. elif cmsg.ctype == ContextType.IMAGE:
  74. logger.debug("[dingtalk]receive image msg: {}".format(cmsg.content))
  75. elif cmsg.ctype == ContextType.PATPAT:
  76. logger.debug("[dingtalk]receive patpat msg: {}".format(cmsg.content))
  77. elif cmsg.ctype == ContextType.TEXT:
  78. expression = cmsg.my_msg
  79. cmsg.content = conf()["group_chat_prefix"][0] + cmsg.content
  80. context = self._compose_context(cmsg.ctype, cmsg.content, isgroup=True, msg=cmsg)
  81. context['no_need_at']=True
  82. if context:
  83. self.produce(context)
  84. async def process(self, callback: dingtalk_stream.CallbackMessage):
  85. try:
  86. incoming_message = dingtalk_stream.ChatbotMessage.from_dict(callback.data)
  87. dingtalk_msg = DingTalkMessage(incoming_message)
  88. if incoming_message.conversation_type == '1':
  89. self.handle_single(dingtalk_msg)
  90. else:
  91. self.handle_group(dingtalk_msg)
  92. return AckMessage.STATUS_OK, 'OK'
  93. except Exception as e:
  94. logger.error(e)
  95. return self.FAILED_MSG
  96. def send(self, reply: Reply, context: Context):
  97. incoming_message = context.kwargs['msg'].incoming_message
  98. self.reply_text(reply.content, incoming_message)
  99. # def _compose_context(self, ctype: ContextType, content, **kwargs):
  100. # context = Context(ctype, content)
  101. # context.kwargs = kwargs
  102. # if "origin_ctype" not in context:
  103. # context["origin_ctype"] = ctype
  104. # cmsg = context["msg"]
  105. # context["session_id"] = cmsg.from_user_id
  106. # context["receiver"] = cmsg.other_user_id
  107. # if ctype == ContextType.TEXT:
  108. # # 1.文本请求
  109. # # 图片生成处理
  110. # img_match_prefix = check_prefix(content, conf().get("image_create_prefix"))
  111. # if img_match_prefix:
  112. # content = content.replace(img_match_prefix, "", 1)
  113. # context.type = ContextType.IMAGE_CREATE
  114. # else:
  115. # context.type = ContextType.TEXT
  116. # context.content = content.strip()
  117. # elif context.type == ContextType.VOICE:
  118. # # 2.语音请求
  119. # if "desire_rtype" not in context and conf().get("voice_reply_voice"):
  120. # context["desire_rtype"] = ReplyType.VOICE
  121. # return context