Add user interaction
This commit is contained in:
47
src/main.rs
47
src/main.rs
@@ -3,10 +3,10 @@ use std::{fs::File, io::BufReader};
|
||||
|
||||
use log::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use telegram_bot::CanReplySendMessage;
|
||||
use telegram_bot::{
|
||||
Api, CanGetFile, CanReplySendAudio, InputFileUpload, MessageKind, UpdateKind, Voice,
|
||||
};
|
||||
use telegram_bot::{CanDeleteMessage, CanReplySendMessage};
|
||||
use thiserror::Error;
|
||||
use tokio_stream::StreamExt;
|
||||
|
||||
@@ -43,6 +43,8 @@ enum RuntimeError {
|
||||
FileDecodeError(#[source] ogg_opus::Error),
|
||||
#[error("Cannot encode audio file")]
|
||||
FileEncodeError(#[source] ogg_opus::Error),
|
||||
#[error("The voice message does not contain any audio data")]
|
||||
FileAudioEmpty,
|
||||
#[error("Internal error")]
|
||||
IOError(#[from] std::io::Error),
|
||||
}
|
||||
@@ -70,21 +72,39 @@ async fn main() -> Result<(), UnresolvableError> {
|
||||
// If the received update contains a new message...
|
||||
let update = update?;
|
||||
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;
|
||||
match result {
|
||||
Ok(audio) => {
|
||||
api.send(
|
||||
message.audio_reply(InputFileUpload::with_data(audio, "amplified.ogg")),
|
||||
message.audio_reply(InputFileUpload::with_data(
|
||||
audio,
|
||||
"amplified.ogg",
|
||||
)),
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
Err(err) => {
|
||||
error!("{:?}", err);
|
||||
match err {
|
||||
RuntimeError::FileAudioEmpty => {}
|
||||
_ => error!("{:?}", err),
|
||||
}
|
||||
api.send(message.text_reply(format!("Error: {}", err)))
|
||||
.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 amplification_factor = 2;
|
||||
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) {
|
||||
break;
|
||||
}
|
||||
@@ -141,17 +161,26 @@ async fn handle_voice_message(
|
||||
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 clipping_samples = 0;
|
||||
for sample in modified_audio.iter_mut() {
|
||||
if *sample == 0 {
|
||||
continue;
|
||||
}
|
||||
is_empty = false;
|
||||
*sample = sample.checked_mul(factor).unwrap_or_else(|| {
|
||||
clipping_samples += 1;
|
||||
sample.saturating_mul(factor)
|
||||
});
|
||||
}
|
||||
|
||||
let clipping_rate = clipping_samples as f64 / modified_audio.len() as f64;
|
||||
info!("samples: {} rate: {}", clipping_samples, clipping_rate);
|
||||
(modified_audio, clipping_rate)
|
||||
if is_empty {
|
||||
return Err(RuntimeError::FileAudioEmpty);
|
||||
}
|
||||
|
||||
let clipping_rate = clipping_samples as f64 / modified_audio.len() as f64;
|
||||
trace!("samples: {} rate: {}", clipping_samples, clipping_rate);
|
||||
Ok((modified_audio, clipping_rate))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user