use actix_multipart::Multipart; use actix_web::Error; use chrono::Utc; use futures_util::StreamExt; use harsh::Harsh; use serde_json::{Map, Value}; use crate::{client, Client}; #[derive(Debug)] pub struct WotLog { /// ID of the log pub id: String, /// Title of the log pub title: String, /// Name of the player pub player: String, /// Is the log public pub public: bool, /// Raw bytes of file as received pub raw: Vec, /// Client type pub client: Client, /// Parsed JSON pub json: Value, } impl WotLog { pub fn new() -> Self { Self { client: Client::None, id: { let harsh = Harsh::default(); let ts = Utc::now(); harsh.encode(&[ts.timestamp_nanos() as u64]) }, player: String::new(), public: false, title: String::new(), raw: Vec::new(), json: Value::Null, } } pub async fn from_payload(payload: Multipart) -> Result { let mut payload = payload; let mut wotlog = WotLog::new(); while let Some(item) = payload.next().await { let mut field = item?; let mut data: Vec = Vec::new(); while let Some(Ok(chunk)) = field.next().await { for byte in chunk { data.push(byte); } } match field.name() { "submit_client" => { //let b: Vec = data.iter().map(|b| *b).collect(); wotlog.client = Client::from(&String::from_utf8_lossy(&data).to_string()) } "submit_player" => wotlog.player = String::from_utf8_lossy(&data).into(), "submit_public" => { if &data == "public".as_bytes() { wotlog.public = true; } } "submit_title" => wotlog.title = String::from_utf8_lossy(&data).into(), "submit_file" => wotlog.raw = data.into(), _ => {} } } Ok(wotlog) } /// Read and parse the log pub fn parse_log(self: &mut Self) -> Result<(), Error> { let mut map: Map = Map::new(); map.insert("id".into(), self.id.clone().into()); map.insert("player".into(), self.player.clone().into()); map.insert("title".into(), self.title.clone().into()); match self.client { Client::Mudlet => { map.insert("replay".into(), client::mudlet::parse_log(&self.raw)?.into()); } Client::TinTin => (), Client::ZMud => (), Client::None => (), }; self.json = map.into(); Ok(()) } }