renders to html string

main
Ashelyn Dawn 1 year ago
parent 95ce2d4668
commit ef3bddbee4

895
Cargo.lock generated

File diff suppressed because it is too large Load Diff

@ -6,8 +6,11 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
chrono = "0.4.23"
clap = {version ="4.1.4", features = ["derive"]}
flate2 = "1.0.25"
futures = { version = "0.3.26", features = ["executor"] }
serde = {version ="1.0.152", features = ["derive"]}
serde_json = "1.0.93"
tar = "0.4.38"
yew = { version = "0.20.0", features = ["ssr"] }

@ -1,13 +1,13 @@
use serde::Deserialize;
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Outbox {
pub total_items: u32,
pub ordered_items: Vec<Item>,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Person {
pub id: String,
@ -20,7 +20,7 @@ pub struct Person {
pub attachments: Option<Vec<Attachment>>,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
#[serde(tag = "type")]
pub enum Item {
#[serde(rename = "Create")]
@ -40,7 +40,7 @@ pub enum Item {
},
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct CommonFields {
id: String,
actor: String,
@ -49,7 +49,7 @@ pub struct CommonFields {
cc: Vec<String>,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase")]
pub struct Post {
summary: Option<String>,
@ -66,7 +66,7 @@ pub struct Post {
quote_uri: Option<String>,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
#[serde(rename_all = "camelCase", tag = "type")]
pub enum Attachment {
#[serde(rename = "Document", rename_all = "camelCase")]
@ -83,18 +83,18 @@ pub enum Attachment {
Property { name: String, value: String },
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Tag {
href: String,
name: String,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct Collection {
first: CollectionPage,
}
#[derive(Deserialize, Debug)]
#[derive(Deserialize, Debug, PartialEq, Clone)]
pub struct CollectionPage {
items: Vec<String>,
}

@ -1,3 +1,4 @@
use chrono::{DateTime, NaiveDateTime};
use clap::Parser;
use flate2::read::GzDecoder;
use serde_json;
@ -8,11 +9,13 @@ use crate::{
cli::GeneratorOptions,
data::{Outbox, Person},
error::Ærror,
render::render,
};
mod cli;
mod data;
mod error;
mod render;
fn main() {
let result = generate();
@ -27,11 +30,12 @@ fn generate() -> Result<(), Ærror> {
let args = GeneratorOptions::parse();
setup_dirs(&args)?;
let (outbox_text, actor_text) = read_archive(&args)?;
let (outbox_text, actor_text, archive_time) = read_archive(&args)?;
let (outbox, author) = parse_json(outbox_text, actor_text)?;
println!("{:?}\n", outbox.ordered_items.first().unwrap());
println!("{:?}", author);
let output_str = render(outbox, author, archive_time)?;
println!("{}", output_str);
Ok(())
}
@ -55,7 +59,9 @@ fn setup_dirs(args: &GeneratorOptions) -> Result<(), crate::error::Ærror> {
Ok(())
}
fn read_archive(args: &GeneratorOptions) -> Result<(String, String), crate::error::Ærror> {
fn read_archive(
args: &GeneratorOptions,
) -> Result<(String, String, DateTime<chrono::Utc>), crate::error::Ærror> {
let path = &args.archive_file;
let tar_gz = File::open(path)?;
@ -64,6 +70,7 @@ fn read_archive(args: &GeneratorOptions) -> Result<(String, String), crate::erro
let mut outbox_text = String::new();
let mut actor_text = String::new();
let mut archive_time: Option<DateTime<chrono::Utc>> = None;
for (_, file) in archive.entries()?.enumerate() {
let mut file = file?;
@ -74,6 +81,14 @@ fn read_archive(args: &GeneratorOptions) -> Result<(String, String), crate::erro
path_str = String::from_str(&path.to_string_lossy()).unwrap();
}
if archive_time.is_none() {
let mtime = file.header().mtime()?;
archive_time = Some(DateTime::<chrono::Utc>::from_utc(
NaiveDateTime::from_timestamp_opt(mtime as i64, 0).unwrap(),
chrono::Utc,
));
}
if path_str.starts_with("media_attachments") {
file.unpack_in(&args.output_dir)?;
} else {
@ -95,6 +110,10 @@ fn read_archive(args: &GeneratorOptions) -> Result<(String, String), crate::erro
}
}
if archive_time.is_none() {
return Err(Ærror::new_str("No files in archive"));
}
if outbox_text.len() < 1 {
return Err(Ærror::new_str("No outbox.json in archive"));
}
@ -103,7 +122,7 @@ fn read_archive(args: &GeneratorOptions) -> Result<(String, String), crate::erro
return Err(Ærror::new_str("No actor.json in archive"));
}
Ok((outbox_text, actor_text))
Ok((outbox_text, actor_text, archive_time.unwrap()))
}
fn parse_json(

@ -0,0 +1,62 @@
use chrono::DateTime;
use futures::executor;
use yew::{function_component, html, Html, ServerRenderer};
use crate::{
data::{Outbox, Person},
error::Ærror,
};
#[derive(yew::Properties, PartialEq)]
struct Props {
pub outbox: Outbox,
pub author: Person,
pub archive_time: DateTime<chrono::Utc>,
}
pub fn render(
outbox: Outbox,
author: Person,
archive_time: DateTime<chrono::Utc>,
) -> Result<String, Ærror> {
let output_string = executor::block_on(render_async(outbox, author, archive_time));
Ok(output_string)
}
async fn render_async(
outbox: Outbox,
author: Person,
archive_time: DateTime<chrono::Utc>,
) -> String {
let renderer = ServerRenderer::<Layout>::with_props(move || -> Props {
Props {
outbox,
author,
archive_time,
}
})
.hydratable(false);
renderer.render().await
}
#[function_component]
fn Layout(props: &Props) -> Html {
html! {
<>
<ProfileHeader outbox={props.outbox.clone()} author={props.author.clone()} archive_time={props.archive_time}/>
</>
}
}
#[function_component]
fn ProfileHeader(props: &Props) -> Html {
html! {
<p>
{"Generated on "}
{props.archive_time.to_rfc2822()}
</p>
}
}
Loading…
Cancel
Save