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, pub messages: Vec, pub timestamps: HashSet, pub media_index: usize, } pub struct ProjectRaw { pub project: Project, pub zip: ZipArchive>> } impl Project { pub async fn load(pathstr: String) -> io::Result { 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; } }