diff --git a/Cargo.lock b/Cargo.lock index ce81de8..0d4dfd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -25,14 +25,14 @@ dependencies = [ "http-signature-normalization", "http-signature-normalization-reqwest", "httpdate", - "hyper", + "hyper 0.14.28", "itertools", "moka", "once_cell", "openssl", "pin-project-lite", "regex", - "reqwest", + "reqwest 0.11.27", "reqwest-middleware", "serde", "serde_json", @@ -91,7 +91,7 @@ dependencies = [ "encoding_rs", "flate2", "futures-core", - "h2", + "h2 0.3.26", "http 0.2.12", "httparse", "httpdate", @@ -477,7 +477,7 @@ dependencies = [ "headers", "http 0.2.12", "http-body 0.4.6", - "hyper", + "hyper 0.14.28", "itoa", "matchit", "memchr", @@ -538,6 +538,12 @@ version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "base64ct" version = "1.6.0" @@ -1372,6 +1378,25 @@ dependencies = [ "tracing", ] +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 1.1.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1553,7 +1578,7 @@ dependencies = [ "base64 0.13.1", "http-signature-normalization", "httpdate", - "reqwest", + "reqwest 0.11.27", "reqwest-middleware", "sha2", "thiserror", @@ -1588,7 +1613,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -1602,6 +1627,26 @@ dependencies = [ "want", ] +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2 0.4.4", + "http 1.1.0", + "http-body 1.0.0", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -1609,10 +1654,46 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper", + "hyper 0.14.28", + "native-tls", + "tokio", + "tokio-native-tls", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper 1.3.1", + "hyper-util", "native-tls", "tokio", "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http 1.1.0", + "http-body 1.0.0", + "hyper 1.3.1", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", ] [[package]] @@ -1826,10 +1907,13 @@ dependencies = [ "lazy_static", "num_cpus", "rand", + "reqwest 0.12.4", "sea-orm", "serde", + "serde_derive", "serde_json", "thiserror", + "time", "tokio", "tracing", "url", @@ -2458,11 +2542,11 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper", - "hyper-tls", + "hyper 0.14.28", + "hyper-tls 0.5.0", "ipnet", "js-sys", "log", @@ -2472,7 +2556,7 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "serde_urlencoded", @@ -2487,7 +2571,51 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "winreg", + "winreg 0.50.0", +] + +[[package]] +name = "reqwest" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-channel", + "futures-core", + "futures-util", + "h2 0.4.4", + "http 1.1.0", + "http-body 1.0.0", + "http-body-util", + "hyper 1.3.1", + "hyper-tls 0.6.0", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "mime_guess", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile 2.1.2", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.52.0", ] [[package]] @@ -2499,7 +2627,7 @@ dependencies = [ "anyhow", "async-trait", "http 0.2.12", - "reqwest", + "reqwest 0.11.27", "serde", "task-local-extensions", "thiserror", @@ -2647,6 +2775,22 @@ dependencies = [ "base64 0.21.7", ] +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64 0.22.1", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" + [[package]] name = "rustls-webpki" version = "0.101.7" @@ -2819,18 +2963,18 @@ checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", @@ -3023,7 +3167,7 @@ dependencies = [ "percent-encoding", "rust_decimal", "rustls", - "rustls-pemfile", + "rustls-pemfile 1.0.4", "serde", "serde_json", "sha2", @@ -3494,6 +3638,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", + "tokio", "tower-layer", "tower-service", "tracing", @@ -4036,6 +4181,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "wyz" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index e9a2f4d..973d159 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,6 +29,9 @@ serde_json = "1.0.115" chrono = "0.4.38" lazy_static = "1.4.0" async_once = "0.2.6" +reqwest = { version = "0.12.4", features = ["blocking", "json", "multipart"] } +time = { version = "0.3.36", features = ["serde"] } +serde_derive = "1.0.201" [dependencies.sea-orm] version = "0.12.0" diff --git a/src/lysand/mod.rs b/src/lysand/mod.rs index 15ee7f6..c1ee410 100644 --- a/src/lysand/mod.rs +++ b/src/lysand/mod.rs @@ -1 +1,3 @@ pub mod objects; +pub mod superx; +pub mod test; diff --git a/src/lysand/objects.rs b/src/lysand/objects.rs index 75b95f8..24ded89 100644 --- a/src/lysand/objects.rs +++ b/src/lysand/objects.rs @@ -1,13 +1,135 @@ +extern crate serde; // 1.0.68 +extern crate serde_derive; // 1.0.68 + +use std::{ + collections::HashMap, + fmt::{Display, Formatter}, +}; + +use serde::{ser::SerializeMap, Deserialize, Deserializer, Serialize, Serializer}; + +use time::{ + format_description::well_known::{iso8601, Iso8601}, + OffsetDateTime, +}; use url::Url; +const FORMAT: Iso8601<6651332276412969266533270467398074368> = Iso8601::< + { + iso8601::Config::DEFAULT + .set_year_is_six_digits(false) + .encode() + }, +>; +time::serde::format_description!(iso_lysand, OffsetDateTime, FORMAT); + +fn sort_alphabetically( + value: &T, + serializer: S, +) -> Result { + let value = serde_json::to_value(value).map_err(serde::ser::Error::custom)?; + value.serialize(serializer) +} + +#[derive(Serialize)] +pub struct SortAlphabetically(#[serde(serialize_with = "sort_alphabetically")] pub T); + +#[derive(Debug, Serialize, Deserialize, Clone)] pub enum LysandType { User, + Note, + Patch, + Like, + Dislike, + Follow, + FollowAccept, + FollowReject, + Undo, + Extension, + ServerMetadata, } -pub struct User { +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct PublicKey { public_key: String, + actor: Url, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ContentHash { + md5: Option, + sha1: Option, + sha256: Option, + sha512: Option, +} + +#[derive(Debug, Clone)] +struct ContentFormat { + x: HashMap, +} + +impl Serialize for ContentFormat { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + let mut seq = serializer.serialize_map(Some(self.x.len()))?; + for (k, v) in &self.x { + seq.serialize_entry(&k.to_string(), &v)?; + } + seq.end() + } +} +impl<'de> Deserialize<'de> for ContentFormat { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + let map = HashMap::deserialize(deserializer)?; + Ok(ContentFormat { x: map }) + } +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +struct FieldKV { + key: ContentFormat, + value: ContentFormat, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct ContentEntry { + content: String, + description: Option, + size: Option, + hash: Option, + blurhash: Option, + fps: Option, + width: Option, + height: Option, + duration: Option, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct User { + public_key: PublicKey, + #[serde(rename = "type")] + rtype: LysandType, id: String, uri: Url, - created_at: String, + #[serde(with = "iso_lysand")] + created_at: OffsetDateTime, display_name: Option, + // TODO bio: Option, + inbox: Url, + outbox: Url, + featured: Url, + followers: Url, + following: Url, + likes: Url, + dislikes: Url, + username: String, + bio: Option, + avatar: Option, + header: Option, + fields: Option>, } diff --git a/src/lysand/superx.rs b/src/lysand/superx.rs new file mode 100644 index 0000000..d8d8f92 --- /dev/null +++ b/src/lysand/superx.rs @@ -0,0 +1,35 @@ +use super::objects::SortAlphabetically; + +pub async fn deserialize_user(data: String) -> anyhow::Result { + let user: super::objects::User = serde_json::from_str(&data)?; + Ok(user) +} + +pub async fn serialize_user(user: super::objects::User) -> anyhow::Result { + let data = serde_json::to_string(&SortAlphabetically(&user))?; + Ok(data) +} + +pub async fn deserialize_lysand_type(data: String) -> anyhow::Result { + let lysand_type: super::objects::LysandType = serde_json::from_str(&data)?; + Ok(lysand_type) +} + +pub async fn serialize_lysand_type( + lysand_type: super::objects::LysandType, +) -> anyhow::Result { + let data = serde_json::to_string(&lysand_type)?; + Ok(data) +} + +#[inline] +pub fn request_client() -> reqwest::Client { + reqwest::Client::builder() + .user_agent(concat!( + env!("CARGO_PKG_NAME"), + "/", + env!("CARGO_PKG_VERSION"), + )) + .build() + .unwrap() +} diff --git a/src/lysand/test.rs b/src/lysand/test.rs new file mode 100644 index 0000000..50b3a5b --- /dev/null +++ b/src/lysand/test.rs @@ -0,0 +1,26 @@ +use crate::lysand::objects::SortAlphabetically; + +use super::superx::request_client; + +pub async fn main() -> anyhow::Result<()> { + let client = request_client(); + + println!("Requesting user"); + let response = client + .get("https://social.lysand.org/users/018ec082-0ae1-761c-b2c5-22275a611771") + .send() + .await?; + println!("Response: {:?}", response); + let user_json = response.text().await?; + println!("User JSON: {:?}", user_json); + let user = super::superx::deserialize_user(user_json).await?; + + println!("\n\n\nUser: "); + print!("{:#?}", user); + + println!("\n\n\nas JSON:"); + let user_json = serde_json::to_string_pretty(&SortAlphabetically(&user))?; + println!("{}", user_json); + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 9b06245..953308c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -149,6 +149,10 @@ static FEDERATION_CONFIG: OnceLock> = OnceLock::new(); async fn main() -> actix_web::Result<(), anyhow::Error> { env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + //TODO remove this + lysand::test::main().await?; + return Ok(()); + let ap_id = Url::parse(&format!( "https://{}/{}", DOMAIN.to_string(),