93 lines
2.6 KiB
Rust
93 lines
2.6 KiB
Rust
use std::{collections::HashSet, io::{self, Cursor, Read, Write}, path::PathBuf, process::exit};
|
|
|
|
use serde::{Deserialize, Serialize};
|
|
use tokio::{fs::File, io::{AsyncReadExt, AsyncWriteExt, BufWriter}};
|
|
use zip::{write::FileOptions, ZipArchive, ZipWriter};
|
|
|
|
use super::{message::Message, user::User};
|
|
|
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
|
pub struct Project {
|
|
pub users: Vec<User>,
|
|
pub messages: Vec<Message>,
|
|
pub timestamps: HashSet<usize>,
|
|
pub media_index: usize,
|
|
}
|
|
|
|
pub struct ProjectRaw {
|
|
pub project: Project,
|
|
pub zip: ZipArchive<Cursor<Vec<u8>>>
|
|
}
|
|
|
|
impl Project {
|
|
pub async fn load(pathstr: String) -> io::Result<ProjectRaw> {
|
|
let path = PathBuf::from(pathstr);
|
|
|
|
if !path.exists() {
|
|
return Err(io::Error::new(io::ErrorKind::NotFound, "File does not exist!"));
|
|
}
|
|
|
|
let mut file = File::open(path).await?;
|
|
let mut buffer = Vec::new();
|
|
file.read_to_end(&mut buffer).await?;
|
|
|
|
let cursor = Cursor::new(buffer);
|
|
let archive = ZipArchive::new(cursor)?;
|
|
|
|
let mut copy_archive = archive.clone();
|
|
let mut project_file = copy_archive.by_name("project.json").unwrap_or_else(|_| {
|
|
eprintln!("Invalid project format!");
|
|
exit(1);
|
|
});
|
|
|
|
let mut json_content = String::new();
|
|
project_file.read_to_string(&mut json_content)?;
|
|
|
|
let data: Project = serde_json::from_str(&json_content)
|
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
|
|
|
Ok(ProjectRaw {
|
|
project: data,
|
|
zip: archive
|
|
})
|
|
}
|
|
|
|
pub async fn save(&self, file_path: String) -> io::Result<()> {
|
|
let contents = serde_json::to_string(&self)
|
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
|
|
|
|
let file = File::create(file_path).await?;
|
|
let mut writer = BufWriter::new(file);
|
|
|
|
let mut buffer = Cursor::new(Vec::new());
|
|
|
|
{
|
|
let mut zip = ZipWriter::new(&mut buffer);
|
|
|
|
let options = FileOptions::default().unix_permissions(0o755);
|
|
zip.add_directory("media/", options)?;
|
|
|
|
zip.start_file("project.json", options)?;
|
|
zip.write_all(contents.as_bytes())?;
|
|
|
|
zip.finish()?;
|
|
}
|
|
|
|
writer.write_all(&buffer.into_inner()).await?;
|
|
writer.flush().await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
pub fn push_msg(&mut self, message: &Message) -> bool {
|
|
if self.timestamps.contains(&message.timestamp) {
|
|
return false;
|
|
}
|
|
|
|
self.timestamps.insert(message.timestamp);
|
|
self.messages.push(message.clone());
|
|
|
|
return true;
|
|
}
|
|
}
|