mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-07-24 13:26:08 +00:00
Feat/lark file and audio (#1874)
* fix: n8n streaming no sequence bug * feat:add lark file and audio fix: webhook * feat:add lark file and audio fix: webhook * 更新 n8nsvapi.py * del : print and log
This commit is contained in:
@@ -13,6 +13,9 @@ import time
|
|||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
from Crypto.Cipher import AES
|
from Crypto.Cipher import AES
|
||||||
|
import tempfile
|
||||||
|
import os
|
||||||
|
import mimetypes
|
||||||
|
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import lark_oapi.ws.exception
|
import lark_oapi.ws.exception
|
||||||
@@ -241,6 +244,7 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
|
|||||||
|
|
||||||
lb_msg_list.append(platform_message.Source(id=message.message_id, time=msg_create_time))
|
lb_msg_list.append(platform_message.Source(id=message.message_id, time=msg_create_time))
|
||||||
|
|
||||||
|
|
||||||
if message.message_type == 'text':
|
if message.message_type == 'text':
|
||||||
element_list = []
|
element_list = []
|
||||||
|
|
||||||
@@ -304,6 +308,10 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
|
|||||||
message_content['content'] = [
|
message_content['content'] = [
|
||||||
{'tag': 'file', 'file_key': message_content['file_key'], 'file_name': message_content['file_name']}
|
{'tag': 'file', 'file_key': message_content['file_key'], 'file_name': message_content['file_name']}
|
||||||
]
|
]
|
||||||
|
elif message.message_type == 'audio':
|
||||||
|
message_content['content'] = [
|
||||||
|
{'tag': 'audio', 'file_key': message_content['file_key'], "duration": message_content.get('duration',0)}
|
||||||
|
]
|
||||||
|
|
||||||
for ele in message_content['content']:
|
for ele in message_content['content']:
|
||||||
if ele['tag'] == 'text':
|
if ele['tag'] == 'text':
|
||||||
@@ -334,6 +342,60 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
|
|||||||
image_format = response.raw.headers['content-type']
|
image_format = response.raw.headers['content-type']
|
||||||
|
|
||||||
lb_msg_list.append(platform_message.Image(base64=f'data:{image_format};base64,{image_base64}'))
|
lb_msg_list.append(platform_message.Image(base64=f'data:{image_format};base64,{image_base64}'))
|
||||||
|
elif ele['tag'] == 'audio':
|
||||||
|
file_key = ele['file_key']
|
||||||
|
duration = ele['duration']
|
||||||
|
|
||||||
|
# Download audio file
|
||||||
|
request: GetMessageResourceRequest = (
|
||||||
|
GetMessageResourceRequest.builder()
|
||||||
|
.message_id(message.message_id)
|
||||||
|
.file_key(file_key)
|
||||||
|
.type('file')
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
response: GetMessageResourceResponse = await api_client.im.v1.message_resource.aget(request)
|
||||||
|
|
||||||
|
if not response.success():
|
||||||
|
print(f'Failed to download audio: code: {response.code}, msg: {response.msg}')
|
||||||
|
lb_msg_list.append(platform_message.Plain(text='[Audio file download failed]'))
|
||||||
|
return platform_message.MessageChain(lb_msg_list)
|
||||||
|
|
||||||
|
# Read audio bytes
|
||||||
|
audio_bytes = response.file.read()
|
||||||
|
audio_base64 = base64.b64encode(audio_bytes).decode()
|
||||||
|
|
||||||
|
|
||||||
|
# Get content type from response headers
|
||||||
|
content_type = response.raw.headers.get('content-type', 'audio/mpeg')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mime_main = content_type.split(';')[0].strip()
|
||||||
|
ext = mimetypes.guess_extension(mime_main) or '.bin'
|
||||||
|
temp_dir = tempfile.gettempdir()
|
||||||
|
temp_file_path = os.path.join(temp_dir, f'lark_audio_{file_key}{ext}')
|
||||||
|
|
||||||
|
with open(temp_file_path, 'wb') as f:
|
||||||
|
f.write(audio_bytes)
|
||||||
|
|
||||||
|
# Create Voice message: prefer path/url + length, include base64 as optional data URI
|
||||||
|
lb_msg_list.append(
|
||||||
|
platform_message.Voice(
|
||||||
|
voice_id=file_key,
|
||||||
|
url=f'file://{temp_file_path}',
|
||||||
|
path=temp_file_path,
|
||||||
|
base64=f'data:{content_type};base64,{audio_base64}',
|
||||||
|
length=(duration // 1000) if duration else None,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
except Exception as e:
|
||||||
|
print(f'Error downloading audio: {e}')
|
||||||
|
traceback.print_exc()
|
||||||
|
lb_msg_list.append(platform_message.Plain(text='[Audio file download error]'))
|
||||||
|
|
||||||
elif ele['tag'] == 'file':
|
elif ele['tag'] == 'file':
|
||||||
file_key = ele['file_key']
|
file_key = ele['file_key']
|
||||||
file_name = ele['file_name']
|
file_name = ele['file_name']
|
||||||
@@ -356,12 +418,42 @@ class LarkMessageConverter(abstract_platform_adapter.AbstractMessageConverter):
|
|||||||
file_bytes = response.file.read()
|
file_bytes = response.file.read()
|
||||||
file_base64 = base64.b64encode(file_bytes).decode()
|
file_base64 = base64.b64encode(file_bytes).decode()
|
||||||
|
|
||||||
|
|
||||||
file_format = response.raw.headers['content-type']
|
file_format = response.raw.headers['content-type']
|
||||||
|
|
||||||
|
file_size = len(file_bytes)
|
||||||
|
|
||||||
|
# Determine extension from content-type if possible
|
||||||
|
content_type = response.raw.headers.get('content-type', '')
|
||||||
|
mime_main = content_type.split(';')[0].strip() if content_type else ''
|
||||||
|
ext = mimetypes.guess_extension(mime_main) or ''
|
||||||
|
|
||||||
|
# Ensure a safe filename (avoid path components)
|
||||||
|
safe_name = os.path.basename(file_name).replace('/', '_').replace('\\', '_')
|
||||||
|
if ext and not safe_name.lower().endswith(ext.lower()):
|
||||||
|
filename_with_ext = f'{safe_name}{ext}'
|
||||||
|
else:
|
||||||
|
filename_with_ext = safe_name
|
||||||
|
|
||||||
|
temp_dir = tempfile.gettempdir()
|
||||||
|
temp_file_path = os.path.join(temp_dir, f'lark_{file_key}_{filename_with_ext}')
|
||||||
|
|
||||||
|
with open(temp_file_path, 'wb') as f:
|
||||||
|
f.write(file_bytes)
|
||||||
|
|
||||||
|
# Create File message with local path and file:// URL
|
||||||
lb_msg_list.append(
|
lb_msg_list.append(
|
||||||
platform_message.File(base64=f'data:{file_format};base64,{file_base64}', name=file_name)
|
platform_message.File(
|
||||||
|
id=file_key,
|
||||||
|
name=file_name,
|
||||||
|
size=file_size,
|
||||||
|
url=f'file://{temp_file_path}',
|
||||||
|
path=temp_file_path,
|
||||||
|
base64=f'data:{file_format};base64,{file_base64}', # not including base64 by default to save memory; can be added if needed
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
return platform_message.MessageChain(lb_msg_list)
|
return platform_message.MessageChain(lb_msg_list)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user