aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/main.rs64
1 files changed, 43 insertions, 21 deletions
diff --git a/src/main.rs b/src/main.rs
index e51cd03..194fbb4 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,13 +1,13 @@
use std::{
env::var,
- fs::File,
- io::Cursor,
+ fs::{File, remove_file},
+ io::Read,
time::{Duration, UNIX_EPOCH},
};
use anyhow::Result;
use clokwerk::{AsyncScheduler, Interval};
-use log::{error, info};
+use log::{debug, error, info};
use rpgpie::{
certificate::Certificate,
message::{SignatureMode, encrypt},
@@ -18,6 +18,8 @@ use teloxide::{Bot, prelude::Requester, types::InputFile};
use tokio::time::sleep;
const MAX_FILE_SIZE: usize = 50000000;
+const BACKUP: &str = "backup";
+const BACKUP_ENCRYPTED: &str = "backup_encrypted";
#[tokio::main]
async fn main() -> Result<()> {
@@ -26,9 +28,7 @@ async fn main() -> Result<()> {
let interval = var("INTERVAL")?.parse::<u32>()?;
scheduler.every(Interval::Hours(interval)).run(|| async {
- info!("Running a backup");
backup().await.unwrap();
- info!("Backup terminated");
});
info!("Program set to backup every {} hours", interval);
@@ -43,6 +43,7 @@ async fn main() -> Result<()> {
}
async fn backup() -> Result<()> {
+ info!("Running a backup");
let chat_id = var("CHAT_ID").unwrap();
let locations: Vec<String> = var("LOCATIONS")
.unwrap()
@@ -51,15 +52,12 @@ async fn backup() -> Result<()> {
.map(|s| s.to_string())
.collect();
- let tar_data = archive(&locations)?;
- let encrypted_tar = encrypt_data("pub.txt", tar_data)?;
+ archive(&locations)?;
+ encrypt_data("pub.txt")?;
+ remove_file(BACKUP)?;
let bot = Bot::from_env();
- let documents: Vec<InputFile> = encrypted_tar
- .chunks(MAX_FILE_SIZE)
- .enumerate()
- .map(|(part, data)| InputFile::memory(data.to_vec()).file_name(format!("part_{:06}", part)))
- .collect();
+ let mut data_to_send = File::open(BACKUP_ENCRYPTED)?;
bot.send_message(
chat_id.clone(),
@@ -67,9 +65,21 @@ async fn backup() -> Result<()> {
)
.await?;
- for x in documents {
+ let mut rr;
+ let mut part = 0;
+ loop {
+ let mut buf = vec![0; MAX_FILE_SIZE];
+ rr = data_to_send.read(&mut buf)?;
+ debug!("Read {} bytes", rr);
+
+ let data = InputFile::memory(buf).file_name(format!("part_{:06}", part));
+
+ if rr == 0 {
+ break;
+ }
+
loop {
- match bot.send_document(chat_id.clone(), x.clone()).await {
+ match bot.send_document(chat_id.clone(), data.clone()).await {
Ok(_) => break,
Err(teloxide::RequestError::RetryAfter(n)) => {
error!("Awaiting {} seconds", n.seconds());
@@ -81,22 +91,33 @@ async fn backup() -> Result<()> {
}
}
}
+ info!("Sent part {}", part);
+ part += 1;
}
+
+ drop(data_to_send);
+ remove_file(BACKUP_ENCRYPTED)?;
+
+ info!("Backup terminated");
Ok(())
}
-fn archive(location: &[String]) -> Result<Vec<u8>> {
- let mut b = Builder::new(Vec::new());
+fn archive(location: &[String]) -> Result<()> {
+ info!("Creating archive");
+ let mut b = Builder::new(File::create(BACKUP)?);
for loc in location {
b.append_dir_all(loc, loc)?;
}
- Ok(b.into_inner()?)
+ b.finish()?;
+ info!("Archive created");
+ Ok(())
}
-fn encrypt_data(key_file: &str, message: Vec<u8>) -> Result<Vec<u8>> {
+fn encrypt_data(key_file: &str) -> Result<()> {
+ info!("Encrypting archive");
let rec = Certificate::load(&mut File::open(key_file)?)?;
- let mut plaintext = Cursor::new(message);
- let mut output = Cursor::new(Vec::new());
+ let mut plaintext = File::open(BACKUP)?;
+ let mut output = File::create(BACKUP_ENCRYPTED)?;
encrypt(
Some(Seipd::SEIPD2),
rec,
@@ -108,5 +129,6 @@ fn encrypt_data(key_file: &str, message: Vec<u8>) -> Result<Vec<u8>> {
&mut output,
false,
)?;
- Ok(output.into_inner())
+ info!("Archive encrypted");
+ Ok(())
}