feat: lysand user

This commit is contained in:
aprilthepink 2024-05-13 21:31:33 +02:00
parent 9e6445d192
commit eec3a037bb
7 changed files with 369 additions and 22 deletions

View file

@ -1 +1,3 @@
pub mod objects;
pub mod superx;
pub mod test;

View file

@ -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;
pub enum LysandType {
User,
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<T: Serialize, S: serde::Serializer>(
value: &T,
serializer: S,
) -> Result<S::Ok, S::Error> {
let value = serde_json::to_value(value).map_err(serde::ser::Error::custom)?;
value.serialize(serializer)
}
pub struct User {
#[derive(Serialize)]
pub struct SortAlphabetically<T: Serialize>(#[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,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PublicKey {
public_key: String,
actor: Url,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct ContentHash {
md5: Option<String>,
sha1: Option<String>,
sha256: Option<String>,
sha512: Option<String>,
}
#[derive(Debug, Clone)]
struct ContentFormat {
x: HashMap<String, ContentEntry>,
}
impl Serialize for ContentFormat {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
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<D>(deserializer: D) -> Result<Self, D::Error>
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<String>,
size: Option<u64>,
hash: Option<ContentHash>,
blurhash: Option<String>,
fps: Option<u64>,
width: Option<u64>,
height: Option<u64>,
duration: Option<u64>,
}
#[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<String>,
// TODO bio: Option<String>,
inbox: Url,
outbox: Url,
featured: Url,
followers: Url,
following: Url,
likes: Url,
dislikes: Url,
username: String,
bio: Option<ContentFormat>,
avatar: Option<ContentFormat>,
header: Option<ContentFormat>,
fields: Option<Vec<FieldKV>>,
}

35
src/lysand/superx.rs Normal file
View file

@ -0,0 +1,35 @@
use super::objects::SortAlphabetically;
pub async fn deserialize_user(data: String) -> anyhow::Result<super::objects::User> {
let user: super::objects::User = serde_json::from_str(&data)?;
Ok(user)
}
pub async fn serialize_user(user: super::objects::User) -> anyhow::Result<String> {
let data = serde_json::to_string(&SortAlphabetically(&user))?;
Ok(data)
}
pub async fn deserialize_lysand_type(data: String) -> anyhow::Result<super::objects::LysandType> {
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<String> {
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()
}

26
src/lysand/test.rs Normal file
View file

@ -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(())
}

View file

@ -149,6 +149,10 @@ static FEDERATION_CONFIG: OnceLock<FederationConfig<State>> = 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(),