mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-21 03:46:11 +00:00
Merge pull request #1152 from RockChinQ/feat/dingtalk-audio
feat(dingtalk): add supports for audio receiving
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
import asyncio
|
import asyncio
|
||||||
|
import json
|
||||||
import dingtalk_stream
|
import dingtalk_stream
|
||||||
from dingtalk_stream import AckMessage
|
from dingtalk_stream import AckMessage
|
||||||
|
|
||||||
@@ -17,7 +18,7 @@ class EchoTextHandler(dingtalk_stream.ChatbotHandler):
|
|||||||
await self.client.update_incoming_message(incoming_message)
|
await self.client.update_incoming_message(incoming_message)
|
||||||
|
|
||||||
return AckMessage.STATUS_OK, 'OK'
|
return AckMessage.STATUS_OK, 'OK'
|
||||||
|
|
||||||
async def get_incoming_message(self):
|
async def get_incoming_message(self):
|
||||||
"""异步等待消息的到来"""
|
"""异步等待消息的到来"""
|
||||||
while self.incoming_message is None:
|
while self.incoming_message is None:
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import base64
|
import base64
|
||||||
|
import json
|
||||||
import time
|
import time
|
||||||
from typing import Callable
|
from typing import Callable
|
||||||
import dingtalk_stream
|
import dingtalk_stream
|
||||||
@@ -92,8 +93,31 @@ class DingTalkClient:
|
|||||||
base64_str = base64.b64encode(file_bytes).decode('utf-8') # 返回字符串格式
|
base64_str = base64.b64encode(file_bytes).decode('utf-8') # 返回字符串格式
|
||||||
return base64_str
|
return base64_str
|
||||||
else:
|
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):
|
async def update_incoming_message(self, message):
|
||||||
"""异步更新 DingTalkClient 中的 incoming_message"""
|
"""异步更新 DingTalkClient 中的 incoming_message"""
|
||||||
message_data = await self.get_message(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):
|
async def get_message(self,incoming_message:dingtalk_stream.chatbot.ChatbotMessage):
|
||||||
try:
|
try:
|
||||||
|
# print(json.dumps(incoming_message.to_dict(), indent=4, ensure_ascii=False))
|
||||||
message_data = {
|
message_data = {
|
||||||
"IncomingMessage":incoming_message,
|
"IncomingMessage":incoming_message,
|
||||||
}
|
}
|
||||||
@@ -160,10 +185,14 @@ class DingTalkClient:
|
|||||||
message_data['Picture'] = await self.download_image(incoming_message.get_image_list()[0])
|
message_data['Picture'] = await self.download_image(incoming_message.get_image_list()[0])
|
||||||
|
|
||||||
message_data['Type'] = 'image'
|
message_data['Type'] = 'image'
|
||||||
|
elif incoming_message.message_type == 'audio':
|
||||||
|
message_data['Audio'] = await self.get_audio_url(incoming_message.to_dict()['content']['downloadCode'])
|
||||||
|
|
||||||
# 删掉开头的@消息
|
message_data['Type'] = 'audio'
|
||||||
if message_data["Content"].startswith("@"+self.robot_name):
|
|
||||||
message_data["Content"][len("@"+self.robot_name):]
|
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:
|
except Exception:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
from typing import Dict, Any, Optional
|
from typing import Dict, Any, Optional
|
||||||
|
import dingtalk_stream
|
||||||
|
|
||||||
class DingTalkEvent(dict):
|
class DingTalkEvent(dict):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -15,7 +16,7 @@ class DingTalkEvent(dict):
|
|||||||
return self.get("Content","")
|
return self.get("Content","")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def incoming_message(self):
|
def incoming_message(self) -> Optional["dingtalk_stream.chatbot.ChatbotMessage"]:
|
||||||
return self.get("IncomingMessage")
|
return self.get("IncomingMessage")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -25,6 +26,10 @@ class DingTalkEvent(dict):
|
|||||||
@property
|
@property
|
||||||
def picture(self):
|
def picture(self):
|
||||||
return self.get("Picture","")
|
return self.get("Picture","")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def audio(self):
|
||||||
|
return self.get("Audio","")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def conversation(self):
|
def conversation(self):
|
||||||
@@ -61,4 +66,4 @@ class DingTalkEvent(dict):
|
|||||||
Returns:
|
Returns:
|
||||||
str: 字符串表示。
|
str: 字符串表示。
|
||||||
"""
|
"""
|
||||||
return f"<WecomEvent {super().__repr__()}>"
|
return f"<DingTalkEvent {super().__repr__()}>"
|
||||||
|
|||||||
@@ -28,16 +28,23 @@ class DingTalkMessageConverter(adapter.MessageConverter):
|
|||||||
return msg.text
|
return msg.text
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def target2yiri(event:DingTalkEvent):
|
async def target2yiri(event:DingTalkEvent, bot_name:str):
|
||||||
yiri_msg_list = []
|
yiri_msg_list = []
|
||||||
yiri_msg_list.append(
|
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:
|
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:
|
if event.picture:
|
||||||
yiri_msg_list.append(platform_message.Image(base64=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)
|
chain = platform_message.MessageChain(yiri_msg_list)
|
||||||
|
|
||||||
@@ -54,18 +61,19 @@ class DingTalkEventConverter(adapter.EventConverter):
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
async def target2yiri(
|
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':
|
if event.conversation == 'FriendMessage':
|
||||||
|
|
||||||
return platform_events.FriendMessage(
|
return platform_events.FriendMessage(
|
||||||
sender=platform_entities.Friend(
|
sender=platform_entities.Friend(
|
||||||
id= 0,
|
id=event.incoming_message.sender_id,
|
||||||
nickname ='nickname',
|
nickname = event.incoming_message.sender_nick,
|
||||||
remark=""
|
remark=""
|
||||||
),
|
),
|
||||||
message_chain = message_chain,
|
message_chain = message_chain,
|
||||||
@@ -73,14 +81,13 @@ class DingTalkEventConverter(adapter.EventConverter):
|
|||||||
source_platform_object=event,
|
source_platform_object=event,
|
||||||
)
|
)
|
||||||
elif event.conversation == 'GroupMessage':
|
elif event.conversation == 'GroupMessage':
|
||||||
message_chain.insert(0, platform_message.At(target="justbot"))
|
|
||||||
sender = platform_entities.GroupMember(
|
sender = platform_entities.GroupMember(
|
||||||
id = 111,
|
id = event.incoming_message.sender_id,
|
||||||
member_name="name",
|
member_name=event.incoming_message.sender_nick,
|
||||||
permission= 'MEMBER',
|
permission= 'MEMBER',
|
||||||
group = platform_entities.Group(
|
group = platform_entities.Group(
|
||||||
id = 111,
|
id = event.incoming_message.conversation_id,
|
||||||
name = 'MEMBER',
|
name = event.incoming_message.conversation_title,
|
||||||
permission=platform_entities.Permission.Member
|
permission=platform_entities.Permission.Member
|
||||||
),
|
),
|
||||||
special_title='',
|
special_title='',
|
||||||
@@ -117,6 +124,8 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter):
|
|||||||
missing_keys = [key for key in required_keys if key not in config]
|
missing_keys = [key for key in required_keys if key not in config]
|
||||||
if missing_keys:
|
if missing_keys:
|
||||||
raise ParamNotEnoughError("钉钉缺少相关配置项,请查看文档或联系管理员")
|
raise ParamNotEnoughError("钉钉缺少相关配置项,请查看文档或联系管理员")
|
||||||
|
|
||||||
|
self.bot_account_id = self.config["robot_name"]
|
||||||
|
|
||||||
self.bot = DingTalkClient(
|
self.bot = DingTalkClient(
|
||||||
client_id=config["client_id"],
|
client_id=config["client_id"],
|
||||||
@@ -153,10 +162,9 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter):
|
|||||||
],
|
],
|
||||||
):
|
):
|
||||||
async def on_message(event: DingTalkEvent):
|
async def on_message(event: DingTalkEvent):
|
||||||
self.bot_account_id = 'justbot'
|
|
||||||
try:
|
try:
|
||||||
return await callback(
|
return await callback(
|
||||||
await self.event_converter.target2yiri(event), self
|
await self.event_converter.target2yiri(event, self.config["robot_name"]), self
|
||||||
)
|
)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc()
|
traceback.print_exc()
|
||||||
@@ -167,7 +175,6 @@ class DingTalkAdapter(adapter.MessagePlatformAdapter):
|
|||||||
self.bot.on_message("GroupMessage")(on_message)
|
self.bot.on_message("GroupMessage")(on_message)
|
||||||
|
|
||||||
async def run_async(self):
|
async def run_async(self):
|
||||||
|
|
||||||
await self.bot.start()
|
await self.bot.start()
|
||||||
|
|
||||||
async def kill(self) -> bool:
|
async def kill(self) -> bool:
|
||||||
|
|||||||
Reference in New Issue
Block a user