172 lines
4.5 KiB
Rust
172 lines
4.5 KiB
Rust
use mxlink::matrix_sdk::ruma::OwnedEventId;
|
|
use mxlink::{MatrixLink, MessageResponseType};
|
|
|
|
use tracing::Instrument;
|
|
|
|
use crate::controller::utils::mime::get_file_extension;
|
|
use crate::{
|
|
Bot,
|
|
agent::{AgentInstance, AgentPurpose, ControllerTrait, provider::TextToSpeechParams},
|
|
entity::MessageContext,
|
|
strings,
|
|
};
|
|
|
|
pub async fn generate_and_send_tts_for_message(
|
|
bot: &Bot,
|
|
matrix_link: MatrixLink,
|
|
message_context: &MessageContext,
|
|
response_type: MessageResponseType,
|
|
speech_agent: &AgentInstance,
|
|
text_message_event_id: &OwnedEventId,
|
|
text_content: &str,
|
|
) -> bool {
|
|
let reaction_event_response = bot
|
|
.reacting()
|
|
.react_no_fail(
|
|
message_context.room(),
|
|
text_message_event_id.clone(),
|
|
strings::PROGRESS_INDICATOR_EMOJI.to_owned(),
|
|
)
|
|
.await;
|
|
|
|
let result = do_generate_and_send_tts_for_message(
|
|
bot,
|
|
matrix_link,
|
|
message_context,
|
|
response_type,
|
|
speech_agent,
|
|
text_content,
|
|
)
|
|
.await;
|
|
|
|
if let Some(reaction_event_response) = reaction_event_response {
|
|
let redaction_reason = if result {
|
|
strings::text_to_speech::redaction_reason_done()
|
|
} else {
|
|
strings::text_to_speech::redaction_reason_failed()
|
|
};
|
|
|
|
bot.messaging()
|
|
.redact_event_no_fail(
|
|
message_context.room(),
|
|
reaction_event_response.event_id,
|
|
Some(redaction_reason.to_owned()),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
result
|
|
}
|
|
|
|
async fn do_generate_and_send_tts_for_message(
|
|
bot: &Bot,
|
|
matrix_link: MatrixLink,
|
|
message_context: &MessageContext,
|
|
response_type: MessageResponseType,
|
|
speech_agent: &AgentInstance,
|
|
text_content: &str,
|
|
) -> bool {
|
|
let params = TextToSpeechParams {
|
|
speed_override: message_context
|
|
.room_config_context()
|
|
.text_to_speech_speed_override(),
|
|
|
|
voice_override: message_context
|
|
.room_config_context()
|
|
.text_to_speech_voice_override(),
|
|
};
|
|
|
|
let text_content = if let Some(text_content) = text_content.strip_prefix(bot.command_prefix()) {
|
|
text_content.trim()
|
|
} else {
|
|
text_content
|
|
};
|
|
|
|
let span = tracing::debug_span!(
|
|
"text_to_speech_generation",
|
|
agent_id = speech_agent.identifier().as_string()
|
|
);
|
|
|
|
let text_to_speech_result = speech_agent
|
|
.controller()
|
|
.text_to_speech(text_content, params)
|
|
.instrument(span)
|
|
.await;
|
|
|
|
let text_to_speech_result = match text_to_speech_result {
|
|
Ok(text_to_speech_result) => text_to_speech_result,
|
|
Err(err) => {
|
|
tracing::warn!(
|
|
"Error in room {} while trying to generate TTS via agent {}: {:?}",
|
|
message_context.room_id(),
|
|
speech_agent.identifier(),
|
|
err,
|
|
);
|
|
|
|
bot.messaging()
|
|
.send_error_markdown_no_fail(
|
|
message_context.room(),
|
|
&strings::agent::error_while_serving_purpose(
|
|
speech_agent.identifier(),
|
|
&AgentPurpose::SpeechToText,
|
|
&err,
|
|
),
|
|
response_type,
|
|
)
|
|
.await;
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
let attachment_body_text = format!(
|
|
"generated-speech.{}",
|
|
get_file_extension(&text_to_speech_result.mime_type)
|
|
);
|
|
|
|
let event_content = matrix_link
|
|
.media()
|
|
.upload_and_prepare_event_content(
|
|
message_context.room(),
|
|
&text_to_speech_result.mime_type,
|
|
text_to_speech_result.bytes,
|
|
&attachment_body_text,
|
|
)
|
|
.await;
|
|
|
|
let mut event_content = match event_content {
|
|
Ok(event_content) => event_content,
|
|
Err(err) => {
|
|
tracing::error!(
|
|
?err,
|
|
"Error in room {} while trying to upload TTS via agent {}",
|
|
message_context.room_id(),
|
|
speech_agent.identifier(),
|
|
);
|
|
|
|
return false;
|
|
}
|
|
};
|
|
|
|
let result = matrix_link
|
|
.messaging()
|
|
.send_event(
|
|
message_context.room(),
|
|
&mut event_content,
|
|
response_type.clone(),
|
|
)
|
|
.await;
|
|
|
|
let Err(err) = result else {
|
|
return true;
|
|
};
|
|
|
|
tracing::error!(
|
|
?err,
|
|
"Error in room {} while trying to send TTS payload",
|
|
message_context.room_id(),
|
|
);
|
|
|
|
false
|
|
}
|