From c72763c4b1293dd478161e68ec950c2ce328b465 Mon Sep 17 00:00:00 2001 From: aprilthepink Date: Tue, 19 Nov 2024 22:15:19 +0100 Subject: [PATCH] feat: initial port to WD4 --- src/versia/conversion.rs | 83 ++++++++++++++------------- src/versia/funcs.rs | 2 +- src/versia/inbox.rs | 7 +-- src/versia/objects.rs | 120 ++++++++++++++------------------------- src/versia/superx.rs | 6 +- src/versia/test.rs | 4 +- 6 files changed, 96 insertions(+), 126 deletions(-) diff --git a/src/versia/conversion.rs b/src/versia/conversion.rs index 53dcd8d..ba8cf91 100644 --- a/src/versia/conversion.rs +++ b/src/versia/conversion.rs @@ -6,6 +6,7 @@ use chrono::{DateTime, TimeZone, Utc}; use reqwest::header::{self, CONTENT_TYPE}; use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set}; use serde::{Deserialize, Serialize}; +use serde_json::to_string; use time::OffsetDateTime; use url::Url; @@ -22,7 +23,7 @@ use crate::{ }; use super::{ - objects::{CategoryType, ContentEntry, ContentFormat, Note, PublicKey}, + objects::{CategoryType, ContentEntry, ContentFormat, Note, PublicKey, UserCollections}, superx::request_client, }; @@ -43,12 +44,12 @@ pub async fn versia_post_from_db( .one(DB.get().unwrap()) .await?; let author = Url::parse(&creator.unwrap().url)?; - let visibility = match post.visibility.as_str() { - "public" => super::objects::VisibilityType::Public, - "followers" => super::objects::VisibilityType::Followers, - "direct" => super::objects::VisibilityType::Direct, - "unlisted" => super::objects::VisibilityType::Unlisted, - _ => super::objects::VisibilityType::Public, + let group = match post.visibility.as_str() { + "public" => Some("public".to_string()), + "followers" => Some("followers".to_string()), + "direct" => None, + //"unlisted" => super::objects::VisibilityType::Unlisted, + _ => Some("public".to_string()), }; //let mut mentions = Vec::new(); //for obj in post.tag.clone() { @@ -60,7 +61,7 @@ pub async fn versia_post_from_db( ContentEntry::from_string(post.content), ); let note = super::objects::Note { - rtype: super::objects::VersiaType::Note, + rtype: "Note".to_string(), id: uuid::Uuid::parse_str(&post.id)?, author: author.clone(), uri: url.clone(), @@ -69,11 +70,10 @@ pub async fn versia_post_from_db( mentions: None, category: Some(CategoryType::Microblog), device: None, - visibility: Some(visibility), previews: None, replies_to: None, quotes: None, - group: None, + group, attachments: None, subject: post.title, is_sensitive: Some(post.sensitive), @@ -190,11 +190,9 @@ pub async fn versia_user_from_db( content_type_header.unwrap().to_str().unwrap().to_string() }); content_format.x.insert(media_type, content_entry); - let mut name = tag.name.chars(); - name.next(); - name.next_back(); + let name = tag.name; emojis.push(super::objects::CustomEmoji { - name: name.as_str().to_string(), + name, url: content_format, }); } @@ -205,20 +203,23 @@ pub async fn versia_user_from_db( let extensions = super::objects::ExtensionSpecs { custom_emojis: emojis, }; + let collections = UserCollections { + outbox: outbox_url, + followers: followers_url, + following: following_url, + featured: featured_url, + }; let user = super::objects::User { - rtype: super::objects::VersiaType::User, + rtype: "User".to_string(), id: uuid::Uuid::parse_str(&user.id)?, uri: url.clone(), username: user.username, display_name, inbox: inbox_url, - outbox: outbox_url, - followers: followers_url, - following: following_url, - featured: featured_url, likes: likes_url, dislikes: dislikes_url, bio: Some(bio), + collections, avatar, header, fields: Some(fields), @@ -226,10 +227,12 @@ pub async fn versia_user_from_db( created_at: OffsetDateTime::from_unix_timestamp(user.created_at.timestamp()).unwrap(), public_key: PublicKey { actor: url.clone(), - public_key: "AAAAC3NzaC1lZDI1NTE5AAAAIMxsX+lEWkHZt9NOvn9yYFP0Z++186LY4b97C4mwj/f2" + key: "AAAAC3NzaC1lZDI1NTE5AAAAIMxsX+lEWkHZt9NOvn9yYFP0Z++186LY4b97C4mwj/f2" .to_string(), // dummy key + algorithm: "ed25519".to_string(), }, extensions: Some(extensions), + manually_approves_followers: false, }; Ok(user) } @@ -418,8 +421,8 @@ pub async fn db_user_from_url(url: Url) -> anyhow::Result ), summary: Set(option_content_format_text(ls_user.bio).await), updated_at: Set(Some(Utc::now())), - followers: Set(Some(ls_user.followers.to_string())), - following: Set(Some(ls_user.following.to_string())), + followers: Set(Some(ls_user.collections.followers.to_string())), + following: Set(Some(ls_user.collections.following.to_string())), ap_json: Set(Some(serde_json::to_string(&ap_json).unwrap())), ..Default::default() }; @@ -464,33 +467,33 @@ pub async fn receive_versia_note( mentions.push(obj.href.clone()); } let to = match note - .visibility + .group .clone() - .unwrap_or(super::objects::VisibilityType::Public) + .unwrap_or("nothing".to_string()).as_str() { - super::objects::VisibilityType::Public => { - let mut vec = vec![public(), Url::parse(&user.followers.to_string().as_str())?]; + "public" => { + let mut vec = vec![public(), Url::parse(&user.collections.followers.to_string().as_str())?]; vec.append(&mut mentions.clone()); vec } - super::objects::VisibilityType::Followers => { - let mut vec = vec![Url::parse(&user.followers.to_string().as_str())?]; + "unlisted" => { + let mut vec = vec![Url::parse(&user.collections.followers.to_string().as_str())?]; vec.append(&mut mentions.clone()); vec } - super::objects::VisibilityType::Direct => mentions.clone(), - super::objects::VisibilityType::Unlisted => { - let mut vec = vec![Url::parse(&user.followers.to_string().as_str())?]; + "followers" => { + let mut vec = vec![Url::parse(&user.collections.followers.to_string().as_str())?]; vec.append(&mut mentions.clone()); vec } + _ => mentions.clone(), }; let cc = match note - .visibility + .group .clone() - .unwrap_or(super::objects::VisibilityType::Public) + .unwrap_or("nothing".to_string()).as_str() { - super::objects::VisibilityType::Unlisted => Some(vec![public()]), + "unlisted" => Some(vec![public()]), _ => None, }; let reply: Option> = @@ -542,14 +545,14 @@ pub async fn receive_versia_note( }; let visibility = match note - .visibility + .group .clone() - .unwrap_or(super::objects::VisibilityType::Public) + .unwrap_or("nothing".to_string()).as_str() { - super::objects::VisibilityType::Public => "public", - super::objects::VisibilityType::Followers => "followers", - super::objects::VisibilityType::Direct => "direct", - super::objects::VisibilityType::Unlisted => "unlisted", + "public" => "public", + "followers" => "followers", + "unlisted" => "unlisted", + _ => "direct", }; if let Some(obj) = note.replies_to { println!("Quoting: {}", db_post_from_url(obj).await?.url); diff --git a/src/versia/funcs.rs b/src/versia/funcs.rs index a3b3458..0ed14c7 100644 --- a/src/versia/funcs.rs +++ b/src/versia/funcs.rs @@ -37,7 +37,7 @@ pub async fn send_follow_accept_to_versia(model: follow_relation::Model) -> anyh let versia_followee = versia_user_from_db(followee_model).await?; let entity = FollowResult { - rtype: super::objects::VersiaType::FollowAccept, + rtype: "FollowAccept".to_string(), id, uri, created_at: OffsetDateTime::now_utc(), diff --git a/src/versia/inbox.rs b/src/versia/inbox.rs index cbf29ca..7d656cb 100644 --- a/src/versia/inbox.rs +++ b/src/versia/inbox.rs @@ -21,7 +21,6 @@ use url::Url; use super::{ conversion::versia_user_from_db, http::{versia_url_to_user, versia_url_to_user_and_model}, - objects::VersiaType, }; pub async fn inbox_entry(json: &str) -> Result<()> { @@ -35,9 +34,6 @@ pub async fn inbox_entry(json: &str) -> Result<()> { Some("Note") => { let note: super::objects::Note = serde_json::from_str(json)?; } - Some("Patch") => { - let patch: super::objects::Patch = serde_json::from_str(json)?; - } Some("Follow") => { let follow_req: super::objects::Follow = serde_json::from_str(json)?; follow_request(follow_req).await?; @@ -48,6 +44,9 @@ pub async fn inbox_entry(json: &str) -> Result<()> { Some("FollowReject") => { let follow_rej: super::objects::FollowResult = serde_json::from_str(json)?; } + Some("Unfollow") => { + let unfollow: super::objects::Unfollow = serde_json::from_str(json)?; + } // Add more cases for other types as needed _ => { return Err(anyhow::anyhow!( diff --git a/src/versia/objects.rs b/src/versia/objects.rs index a20bcf0..f8b5e37 100644 --- a/src/versia/objects.rs +++ b/src/versia/objects.rs @@ -35,21 +35,6 @@ fn sort_alphabetically( #[derive(Serialize)] pub struct SortAlphabetically(#[serde(serialize_with = "sort_alphabetically")] pub T); -#[derive(Debug, Serialize, Deserialize, Clone)] -pub enum VersiaType { - User, - Note, - Patch, - Like, - Dislike, - Follow, - FollowAccept, - FollowReject, - Undo, - Extension, - ServerMetadata, -} - #[derive(Debug, Serialize, Deserialize, Clone)] pub enum CategoryType { Microblog, @@ -61,19 +46,10 @@ pub enum CategoryType { Messaging, } -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(rename_all = "snake_case")] -pub enum VisibilityType { - Public, - Unlisted, - Followers, - Direct, -} - #[derive(Debug, Serialize, Deserialize, Clone)] pub enum VersiaExtensions { - #[serde(rename = "pub.versia:microblogging/Announce")] - Announce, + #[serde(rename = "pub.versia:share/Share")] + Share, #[serde(rename = "pub.versia:custom_emojis")] CustomEmojis, #[serde(rename = "pub.versia:reactions/Reaction")] @@ -96,8 +72,9 @@ pub enum VersiaExtensions { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct PublicKey { - pub public_key: String, + pub key: String, pub actor: Url, + pub algorithm: String, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -217,6 +194,7 @@ pub struct FieldKV { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ContentEntry { content: String, + remote: bool, #[serde(skip_serializing_if = "Option::is_none")] description: Option, #[serde(skip_serializing_if = "Option::is_none")] @@ -238,6 +216,7 @@ impl ContentEntry { pub fn from_string(string: String) -> ContentEntry { ContentEntry { content: string, + remote: false, description: None, size: None, hash: None, @@ -254,18 +233,15 @@ impl ContentEntry { pub struct User { pub public_key: PublicKey, #[serde(rename = "type")] - pub rtype: VersiaType, + pub rtype: String, pub id: Uuid, pub uri: Url, #[serde(with = "iso_versia")] pub created_at: OffsetDateTime, #[serde(skip_serializing_if = "Option::is_none")] pub display_name: Option, + pub collections: UserCollections, pub inbox: Url, - pub outbox: Url, - pub featured: Url, - pub followers: Url, - pub following: Url, pub likes: Url, pub dislikes: Url, pub username: String, @@ -280,6 +256,15 @@ pub struct User { pub indexable: bool, #[serde(skip_serializing_if = "Option::is_none")] pub extensions: Option, + pub manually_approves_followers: bool, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct UserCollections { + pub outbox: Url, + pub featured: Url, + pub followers: Url, + pub following: Url, } #[derive(Debug, Serialize, Deserialize, Clone)] @@ -321,7 +306,7 @@ pub struct LinkPreview { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Note { #[serde(rename = "type")] - pub rtype: VersiaType, + pub rtype: String, pub id: Uuid, pub uri: Url, pub author: Url, @@ -349,46 +334,6 @@ pub struct Note { pub subject: Option, #[serde(skip_serializing_if = "Option::is_none")] pub is_sensitive: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub visibility: Option, - //TODO extensions -} - -#[derive(Debug, Serialize, Deserialize, Clone)] -pub struct Patch { - #[serde(rename = "type")] - pub rtype: VersiaType, - pub id: Uuid, - pub uri: Url, - pub author: Url, - #[serde(with = "iso_versia")] - pub created_at: OffsetDateTime, - #[serde(with = "iso_versia")] - pub patched_at: OffsetDateTime, - #[serde(skip_serializing_if = "Option::is_none")] - pub category: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub content: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub device: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub previews: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub group: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub attachments: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub replies_to: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub quotes: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub mentions: Option>, - #[serde(skip_serializing_if = "Option::is_none")] - pub subject: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub is_sensitive: Option, - #[serde(skip_serializing_if = "Option::is_none")] - pub visibility: Option, //TODO extensions } @@ -399,14 +344,14 @@ pub struct Outbox { #[serde(skip_serializing_if = "Option::is_none")] pub next: Option, #[serde(skip_serializing_if = "Option::is_none")] - pub prev: Option, + pub previous: Option, pub items: Vec, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct Follow { #[serde(rename = "type")] - pub rtype: VersiaType, + pub rtype: String, pub id: Uuid, pub uri: Url, pub author: Url, @@ -418,7 +363,7 @@ pub struct Follow { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct FollowResult { #[serde(rename = "type")] - pub rtype: VersiaType, + pub rtype: String, pub id: Uuid, pub uri: Url, pub author: Url, @@ -426,3 +371,26 @@ pub struct FollowResult { pub created_at: OffsetDateTime, pub follower: Url, } + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Unfollow { + #[serde(rename = "type")] + pub rtype: String, + pub id: Uuid, + pub author: Url, + #[serde(with = "iso_versia")] + pub created_at: OffsetDateTime, + pub followee: Url, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Delete { + #[serde(rename = "type")] + pub rtype: String, + pub id: Uuid, + pub author: Option, + #[serde(with = "iso_versia")] + pub created_at: OffsetDateTime, + pub deleted_type: String, + pub deleted: Url, +} diff --git a/src/versia/superx.rs b/src/versia/superx.rs index 714ca94..da6de74 100644 --- a/src/versia/superx.rs +++ b/src/versia/superx.rs @@ -10,13 +10,13 @@ pub async fn serialize_user(user: super::objects::User) -> anyhow::Result anyhow::Result { - let versia_type: super::objects::VersiaType = serde_json::from_str(&data)?; +pub async fn deserialize_versia_type(data: String) -> anyhow::Result { + let versia_type: String = serde_json::from_str(&data)?; Ok(versia_type) } pub async fn serialize_versia_type( - versia_type: super::objects::VersiaType, + versia_type: String, ) -> anyhow::Result { let data = serde_json::to_string(&versia_type)?; Ok(data) diff --git a/src/versia/test.rs b/src/versia/test.rs index dfae98a..489916c 100644 --- a/src/versia/test.rs +++ b/src/versia/test.rs @@ -13,7 +13,7 @@ async fn test_user_serial() { let user = super::superx::deserialize_user(response.text().await.unwrap()) .await .unwrap(); - let response_outbox = client.get(user.outbox.as_str()).send().await.unwrap(); + let response_outbox = client.get(user.collections.outbox.as_str()).send().await.unwrap(); let outbox = super::superx::deserialize_outbox(response_outbox.text().await.unwrap()) .await .unwrap(); @@ -40,7 +40,7 @@ pub async fn main() -> anyhow::Result<()> { let user_json = serde_json::to_string_pretty(&SortAlphabetically(&user))?; println!("{}", user_json); - let response_outbox = client.get(user.outbox.as_str()).send().await?; + let response_outbox = client.get(user.collections.outbox.as_str()).send().await?; let outbox_json = response_outbox.text().await?; let outbox = super::superx::deserialize_outbox(outbox_json).await?;