diff --git a/libs/dingtalk_api/EchoHandler.py b/libs/dingtalk_api/EchoHandler.py index 00ff6c72..4baad637 100644 --- a/libs/dingtalk_api/EchoHandler.py +++ b/libs/dingtalk_api/EchoHandler.py @@ -1,4 +1,5 @@ import asyncio +import json import dingtalk_stream from dingtalk_stream import AckMessage @@ -17,7 +18,7 @@ class EchoTextHandler(dingtalk_stream.ChatbotHandler): await self.client.update_incoming_message(incoming_message) return AckMessage.STATUS_OK, 'OK' - + async def get_incoming_message(self): """异步等待消息的到来""" while self.incoming_message is None: diff --git a/libs/dingtalk_api/api.py b/libs/dingtalk_api/api.py index 905557a6..9e5aca6d 100644 --- a/libs/dingtalk_api/api.py +++ b/libs/dingtalk_api/api.py @@ -1,4 +1,5 @@ import base64 +import json import time from typing import Callable import dingtalk_stream @@ -92,8 +93,31 @@ class DingTalkClient: base64_str = base64.b64encode(file_bytes).decode('utf-8') # 返回字符串格式 return base64_str else: - raise Exception("获取图片失败") - + raise Exception("获取文件失败") + + async def get_audio_url(self,download_code:str): + if not await self.check_access_token(): + await self.get_access_token() + url = 'https://api.dingtalk.com/v1.0/robot/messageFiles/download' + params = { + "downloadCode":download_code, + "robotCode":self.robot_code + } + headers ={ + "x-acs-dingtalk-access-token": self.access_token + } + async with httpx.AsyncClient() as client: + response = await client.post(url, headers=headers, json=params) + if response.status_code == 200: + result = response.json() + download_url = result.get("downloadUrl") + if download_url: + return await self.download_url_to_base64(download_url) + else: + raise Exception("获取音频失败") + else: + raise Exception(f"Error: {response.status_code}, {response.text}") + async def update_incoming_message(self, message): """异步更新 DingTalkClient 中的 incoming_message""" message_data = await self.get_message(message) @@ -133,6 +157,7 @@ class DingTalkClient: async def get_message(self,incoming_message:dingtalk_stream.chatbot.ChatbotMessage): try: + # print(json.dumps(incoming_message.to_dict(), indent=4, ensure_ascii=False)) message_data = { "IncomingMessage":incoming_message, } @@ -160,10 +185,14 @@ class DingTalkClient: message_data['Picture'] = await self.download_image(incoming_message.get_image_list()[0]) message_data['Type'] = 'image' + elif incoming_message.message_type == 'audio': + message_data['Audio'] = await self.get_audio_url(incoming_message.to_dict()['content']['downloadCode']) - # 删掉开头的@消息 - if message_data["Content"].startswith("@"+self.robot_name): - message_data["Content"][len("@"+self.robot_name):] + message_data['Type'] = 'audio' + + copy_message_data = message_data.copy() + del copy_message_data['IncomingMessage'] + # print("message_data:", json.dumps(copy_message_data, indent=4, ensure_ascii=False)) except Exception: traceback.print_exc() diff --git a/libs/dingtalk_api/dingtalkevent.py b/libs/dingtalk_api/dingtalkevent.py index 8f6bdfc1..4feca010 100644 --- a/libs/dingtalk_api/dingtalkevent.py +++ b/libs/dingtalk_api/dingtalkevent.py @@ -1,4 +1,5 @@ from typing import Dict, Any, Optional +import dingtalk_stream class DingTalkEvent(dict): @staticmethod @@ -15,7 +16,7 @@ class DingTalkEvent(dict): return self.get("Content","") @property - def incoming_message(self): + def incoming_message(self) -> Optional["dingtalk_stream.chatbot.ChatbotMessage"]: return self.get("IncomingMessage") @property @@ -25,6 +26,10 @@ class DingTalkEvent(dict): @property def picture(self): return self.get("Picture","") + + @property + def audio(self): + return self.get("Audio","") @property def conversation(self): @@ -61,4 +66,4 @@ class DingTalkEvent(dict): Returns: str: 字符串表示。 """ - return f"" \ No newline at end of file + return f"" diff --git a/pkg/platform/sources/dingtalk.py b/pkg/platform/sources/dingtalk.py index 7d1fc1e0..505ab9a2 100644 --- a/pkg/platform/sources/dingtalk.py +++ b/pkg/platform/sources/dingtalk.py @@ -28,16 +28,23 @@ class DingTalkMessageConverter(adapter.MessageConverter): return msg.text @staticmethod - async def target2yiri(event:DingTalkEvent): + async def target2yiri(event:DingTalkEvent, bot_name:str): yiri_msg_list = [] yiri_msg_list.append( - platform_message.Source(id = '0',time=datetime.datetime.now()) + platform_message.Source(id = event.incoming_message.message_id,time=datetime.datetime.now()) ) + for atUser in event.incoming_message.at_users: + if atUser.dingtalk_id == event.incoming_message.chatbot_user_id: + yiri_msg_list.append(platform_message.At(target=bot_name)) + if event.content: - yiri_msg_list.append(platform_message.Plain(text=event.content)) + text_content = event.content.replace("@"+bot_name, '') + yiri_msg_list.append(platform_message.Plain(text=text_content)) if event.picture: yiri_msg_list.append(platform_message.Image(base64=event.picture)) + if event.audio: + yiri_msg_list.append(platform_message.Voice(base64=event.audio)) chain = platform_message.MessageChain(yiri_msg_list) @@ -54,18 +61,19 @@ class DingTalkEventConverter(adapter.EventConverter): @staticmethod async def target2yiri( - event:DingTalkEvent + event:DingTalkEvent, + bot_name:str ): - message_chain = await DingTalkMessageConverter.target2yiri(event) + message_chain = await DingTalkMessageConverter.target2yiri(event, bot_name) if event.conversation == 'FriendMessage': return platform_events.FriendMessage( sender=platform_entities.Friend( - id= 0, - nickname ='nickname', + id=event.incoming_message.sender_id, + nickname = event.incoming_message.sender_nick, remark="" ), message_chain = message_chain, @@ -73,14 +81,13 @@ class DingTalkEventConverter(adapter.EventConverter): source_platform_object=event, ) elif event.conversation == 'GroupMessage': - message_chain.insert(0, platform_message.At(target="justbot")) sender = platform_entities.GroupMember( - id = 111, - member_name="name", + id = event.incoming_message.sender_id, + member_name=event.incoming_message.sender_nick, permission= 'MEMBER', group = platform_entities.Group( - id = 111, - name = 'MEMBER', + id = event.incoming_message.conversation_id, + name = event.incoming_message.conversation_title, permission=platform_entities.Permission.Member ), special_title='', @@ -117,6 +124,8 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter): missing_keys = [key for key in required_keys if key not in config] if missing_keys: raise ParamNotEnoughError("钉钉缺少相关配置项,请查看文档或联系管理员") + + self.bot_account_id = self.config["robot_name"] self.bot = DingTalkClient( client_id=config["client_id"], @@ -153,10 +162,9 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter): ], ): async def on_message(event: DingTalkEvent): - self.bot_account_id = 'justbot' try: return await callback( - await self.event_converter.target2yiri(event), self + await self.event_converter.target2yiri(event, self.config["robot_name"]), self ) except: traceback.print_exc() @@ -167,7 +175,6 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter): self.bot.on_message("GroupMessage")(on_message) async def run_async(self): - await self.bot.start() async def kill(self) -> bool: