Add user interaction

This commit is contained in:
2021-07-28 11:59:06 +02:00
parent 3d92f3192b
commit 5285eac906

View File

@@ -3,10 +3,10 @@ use std::{fs::File, io::BufReader};
use log::*; use log::*;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use telegram_bot::CanReplySendMessage;
use telegram_bot::{ use telegram_bot::{
Api, CanGetFile, CanReplySendAudio, InputFileUpload, MessageKind, UpdateKind, Voice, Api, CanGetFile, CanReplySendAudio, InputFileUpload, MessageKind, UpdateKind, Voice,
}; };
use telegram_bot::{CanDeleteMessage, CanReplySendMessage};
use thiserror::Error; use thiserror::Error;
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
@@ -43,6 +43,8 @@ enum RuntimeError {
FileDecodeError(#[source] ogg_opus::Error), FileDecodeError(#[source] ogg_opus::Error),
#[error("Cannot encode audio file")] #[error("Cannot encode audio file")]
FileEncodeError(#[source] ogg_opus::Error), FileEncodeError(#[source] ogg_opus::Error),
#[error("The voice message does not contain any audio data")]
FileAudioEmpty,
#[error("Internal error")] #[error("Internal error")]
IOError(#[from] std::io::Error), IOError(#[from] std::io::Error),
} }
@@ -70,21 +72,39 @@ async fn main() -> Result<(), UnresolvableError> {
// If the received update contains a new message... // If the received update contains a new message...
let update = update?; let update = update?;
if let UpdateKind::Message(message) = update.kind { if let UpdateKind::Message(message) = update.kind {
if let MessageKind::Voice { data } = &message.kind { match &message.kind {
MessageKind::Voice { data } => {
let progress_message = api
.send(message.text_reply("On it, give me a sec..."))
.await?;
let result = handle_voice_message(&config, &api, data).await; let result = handle_voice_message(&config, &api, data).await;
match result { match result {
Ok(audio) => { Ok(audio) => {
api.send( api.send(
message.audio_reply(InputFileUpload::with_data(audio, "amplified.ogg")), message.audio_reply(InputFileUpload::with_data(
audio,
"amplified.ogg",
)),
) )
.await?; .await?;
} }
Err(err) => { Err(err) => {
error!("{:?}", err); match err {
RuntimeError::FileAudioEmpty => {}
_ => error!("{:?}", err),
}
api.send(message.text_reply(format!("Error: {}", err))) api.send(message.text_reply(format!("Error: {}", err)))
.await?; .await?;
} }
} }
api.send(progress_message.delete()).await?;
}
MessageKind::Text { data, .. } => {
if data.starts_with("/") {
api.send(message.text_reply("Send or forward voicemessages to me and I'll amplify them for you. Currently, I don't understand any commands.")).await?;
}
}
_ => {}
} }
} }
} }
@@ -125,7 +145,7 @@ async fn handle_voice_message(
let mut last_audio = audio.clone(); let mut last_audio = audio.clone();
let mut amplification_factor = 2; let mut amplification_factor = 2;
loop { loop {
let (current_audio, clipping_rate) = amplify_audio(&audio, amplification_factor); let (current_audio, clipping_rate) = amplify_audio(&audio, amplification_factor)?;
if clipping_rate > 1.0 / (48000.0 * 10.0) { if clipping_rate > 1.0 / (48000.0 * 10.0) {
break; break;
} }
@@ -141,17 +161,26 @@ async fn handle_voice_message(
Ok(ogg_data_out) Ok(ogg_data_out)
} }
fn amplify_audio(original: &[i16], factor: i16) -> (Vec<i16>, f64) { fn amplify_audio(original: &[i16], factor: i16) -> Result<(Vec<i16>, f64), RuntimeError> {
let mut is_empty = true;
let mut modified_audio = original.to_owned(); let mut modified_audio = original.to_owned();
let mut clipping_samples = 0; let mut clipping_samples = 0;
for sample in modified_audio.iter_mut() { for sample in modified_audio.iter_mut() {
if *sample == 0 {
continue;
}
is_empty = false;
*sample = sample.checked_mul(factor).unwrap_or_else(|| { *sample = sample.checked_mul(factor).unwrap_or_else(|| {
clipping_samples += 1; clipping_samples += 1;
sample.saturating_mul(factor) sample.saturating_mul(factor)
}); });
} }
let clipping_rate = clipping_samples as f64 / modified_audio.len() as f64; if is_empty {
info!("samples: {} rate: {}", clipping_samples, clipping_rate); return Err(RuntimeError::FileAudioEmpty);
(modified_audio, clipping_rate) }
let clipping_rate = clipping_samples as f64 / modified_audio.len() as f64;
trace!("samples: {} rate: {}", clipping_samples, clipping_rate);
Ok((modified_audio, clipping_rate))
} }