use std::{ env::var, fs::File, io::Cursor, time::{Duration, UNIX_EPOCH}, }; use anyhow::Result; use log::error; use rpgpie::{ certificate::Certificate, message::{SignatureMode, encrypt}, policy::Seipd, }; use tar::Builder; use teloxide::{Bot, prelude::Requester, types::InputFile}; use tokio::time::sleep; const MAX_FILE_SIZE: usize = 50000000; #[tokio::main] async fn main() -> Result<()> { env_logger::init(); let chat_id = var("CHAT_ID").unwrap(); let locations: Vec = var("LOCATIONS") .unwrap() .trim() .split(':') .map(|s| s.to_string()) .collect(); let tar_data = archive(&locations)?; let encrypted_tar = encrypt_data("pub.txt", tar_data)?; let bot = Bot::from_env(); let documents: Vec = encrypted_tar .chunks(MAX_FILE_SIZE) .enumerate() .map(|(part, data)| InputFile::memory(data.to_vec()).file_name(format!("part_{:06}", part))) .collect(); bot.send_message( chat_id.clone(), format!("{}", UNIX_EPOCH.elapsed()?.as_secs().to_string()), ) .await?; for x in documents { loop { match bot.send_document(chat_id.clone(), x.clone()).await { Ok(_) => break, Err(teloxide::RequestError::RetryAfter(n)) => { error!("Awaiting {} seconds", n.seconds()); sleep(Duration::from_secs(n.seconds() as u64)).await } Err(err) => { error!("{}\nAwaiting 8 seconds", err); sleep(Duration::from_secs(8)).await } } } } Ok(()) } fn archive(location: &[String]) -> Result> { let mut b = Builder::new(Vec::new()); for loc in location { b.append_dir_all(loc, loc)?; } Ok(b.into_inner()?) } fn encrypt_data(key_file: &str, message: Vec) -> Result> { let rec = Certificate::load(&mut File::open(key_file)?)?; let mut plaintext = Cursor::new(message); let mut output = Cursor::new(Vec::new()); encrypt( Some(Seipd::SEIPD2), rec, Vec::new(), Vec::new(), &Vec::new(), &mut plaintext, SignatureMode::Binary, &mut output, false, )?; Ok(output.into_inner()) }