From e0f427a2b96ca2d8fd108b9bab983413065c6932 Mon Sep 17 00:00:00 2001 From: alemi Date: Mon, 15 Jul 2024 13:57:03 +0200 Subject: [PATCH] feat: process and store fields and aliases basically moved_to, also_known_as and actor attachments --- upub/core/Cargo.toml | 2 +- upub/core/src/model/actor.rs | 34 +++++++++++++++- upub/core/src/traits/normalize.rs | 3 ++ upub/migrations/src/lib.rs | 2 + ...001_create_actor_activity_object_tables.rs | 3 ++ ...15_000002_add_actors_fields_and_aliases.rs | 39 +++++++++++++++++++ 6 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 upub/migrations/src/m20240715_000002_add_actors_fields_and_aliases.rs diff --git a/upub/core/Cargo.toml b/upub/core/Cargo.toml index 6b6eff4..dc04d14 100644 --- a/upub/core/Cargo.toml +++ b/upub/core/Cargo.toml @@ -34,6 +34,6 @@ tracing = "0.1" tokio = { version = "1.35", features = ["full"] } # TODO slim this down sea-orm = { version = "0.12", features = ["macros", "sqlx-sqlite", "sqlx-postgres", "runtime-tokio-rustls"] } reqwest = { version = "0.12", features = ["json"] } -apb = { path = "../../apb", features = ["unstructured", "orm", "activitypub-fe", "activitypub-counters", "litepub", "ostatus", "toot"] } +apb = { path = "../../apb", features = ["unstructured", "orm", "did-core", "activitypub-miscellaneous-terms", "activitypub-fe", "activitypub-counters", "litepub", "ostatus", "toot"] } # nodeinfo = "0.0.2" # the version on crates.io doesn't re-export necessary types to build the struct!!! nodeinfo = { git = "https://codeberg.org/thefederationinfo/nodeinfo-rs", rev = "e865094804" } diff --git a/upub/core/src/model/actor.rs b/upub/core/src/model/actor.rs index c092f7d..c9707ed 100644 --- a/upub/core/src/model/actor.rs +++ b/upub/core/src/model/actor.rs @@ -1,6 +1,27 @@ use sea_orm::{entity::prelude::*, QuerySelect, SelectColumns}; -use apb::{ActorMut, ActorType, BaseMut, DocumentMut, EndpointsMut, ObjectMut, PublicKeyMut}; +use apb::{field::OptionalString, ActorMut, ActorType, BaseMut, DocumentMut, EndpointsMut, ObjectMut, PublicKeyMut}; + +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize, sea_orm::FromJsonQueryResult)] +pub struct Field { + pub name: String, + pub content: String, + pub verified_at: Option, + + #[serde(rename = "type")] + pub field_type: String, +} + +impl From for Field { + fn from(value: T) -> Self { + Field { + name: value.name().str().unwrap_or_default(), + content: value.content().str().unwrap_or_default(), + field_type: "PropertyValue".to_string(), // TODO can we try parsing this instead?? + verified_at: None, // TODO where does verified_at come from? extend apb maybe + } + } +} #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)] #[sea_orm(table_name = "actors")] @@ -16,6 +37,7 @@ pub struct Model { pub image: Option, pub icon: Option, pub preferred_username: String, + pub fields: Vec, pub inbox: Option, pub shared_inbox: Option, pub outbox: Option, @@ -28,6 +50,8 @@ pub struct Model { pub private_key: Option, pub published: ChronoDateTimeUtc, pub updated: ChronoDateTimeUtc, + pub also_known_as: Vec, + pub moved_to: Option, } #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] @@ -183,6 +207,12 @@ impl Model { .set_document_type(Some(apb::DocumentType::Image)) .set_url(apb::Node::link(i.clone())) ))) + .set_attachment(apb::Node::array( + self.fields + .into_iter() + .filter_map(|x| serde_json::to_value(&x).ok()) + .collect() + )) .set_published(Some(self.published)) .set_updated(if self.updated != self.published { Some(self.updated) } else { None }) .set_preferred_username(Some(&self.preferred_username)) @@ -203,6 +233,8 @@ impl Model { apb::new() .set_shared_inbox(self.shared_inbox.as_deref()) )) + .set_also_known_as(apb::Node::links(self.also_known_as)) + .set_moved_to(apb::Node::maybe_link(self.moved_to)) .set_discoverable(Some(true)) } } diff --git a/upub/core/src/traits/normalize.rs b/upub/core/src/traits/normalize.rs index 25ad28a..d100390 100644 --- a/upub/core/src/traits/normalize.rs +++ b/upub/core/src/traits/normalize.rs @@ -333,11 +333,14 @@ impl AP { summary: actor.summary().str(), icon: actor.icon().get().and_then(|x| x.url().id().str()), image: actor.image().get().and_then(|x| x.url().id().str()), + fields: actor.attachment().flat().into_iter().filter_map(|x| Some(crate::model::actor::Field::from(x.extract()?))).collect(), inbox: actor.inbox().id().str(), outbox: actor.outbox().id().str(), shared_inbox: actor.endpoints().get().and_then(|x| x.shared_inbox().str()), followers: actor.followers().id().str(), following: actor.following().id().str(), + also_known_as: actor.also_known_as().flat().into_iter().filter_map(|x| x.id().str()).collect(), + moved_to: actor.moved_to().id().str(), published: actor.published().unwrap_or(chrono::Utc::now()), updated: chrono::Utc::now(), following_count: actor.following_count().unwrap_or(0) as i32, diff --git a/upub/migrations/src/lib.rs b/upub/migrations/src/lib.rs index 19be15c..9f21475 100644 --- a/upub/migrations/src/lib.rs +++ b/upub/migrations/src/lib.rs @@ -18,6 +18,7 @@ mod m20240703_000001_add_audience_index; mod m20240703_000002_add_image_to_objects; mod m20240706_000001_add_error_to_jobs; mod m20240715_000001_add_quote_uri_to_objects; +mod m20240715_000002_add_actors_fields_and_aliases; pub struct Migrator; @@ -43,6 +44,7 @@ impl MigratorTrait for Migrator { Box::new(m20240703_000002_add_image_to_objects::Migration), Box::new(m20240706_000001_add_error_to_jobs::Migration), Box::new(m20240715_000001_add_quote_uri_to_objects::Migration), + Box::new(m20240715_000002_add_actors_fields_and_aliases::Migration), ] } } diff --git a/upub/migrations/src/m20240524_000001_create_actor_activity_object_tables.rs b/upub/migrations/src/m20240524_000001_create_actor_activity_object_tables.rs index b3ef14f..e414ef9 100644 --- a/upub/migrations/src/m20240524_000001_create_actor_activity_object_tables.rs +++ b/upub/migrations/src/m20240524_000001_create_actor_activity_object_tables.rs @@ -12,6 +12,7 @@ pub enum Actors { Image, Icon, PreferredUsername, + Fields, // added with migration m20240715_000002 Inbox, SharedInbox, Outbox, @@ -22,6 +23,8 @@ pub enum Actors { StatusesCount, PublicKey, PrivateKey, + AlsoKnownAs, // added with migration m20240715_000002 + MovedTo, // added with migration m20240715_000002 Published, Updated, } diff --git a/upub/migrations/src/m20240715_000002_add_actors_fields_and_aliases.rs b/upub/migrations/src/m20240715_000002_add_actors_fields_and_aliases.rs new file mode 100644 index 0000000..6d8183b --- /dev/null +++ b/upub/migrations/src/m20240715_000002_add_actors_fields_and_aliases.rs @@ -0,0 +1,39 @@ +use sea_orm_migration::prelude::*; + +use crate::m20240524_000001_create_actor_activity_object_tables::Actors; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(Actors::Table) + .add_column(ColumnDef::new(Actors::MovedTo).string().null()) + .add_column(ColumnDef::new(Actors::AlsoKnownAs).json_binary().not_null().default::>(vec![])) + .add_column(ColumnDef::new(Actors::Fields).json_binary().not_null().default::>(vec![])) + .to_owned() + ) + .await?; + + Ok(()) + } + + async fn down(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager + .alter_table( + Table::alter() + .table(Actors::Table) + .drop_column(Actors::MovedTo) + .drop_column(Actors::AlsoKnownAs) + .drop_column(Actors::Fields) + .to_owned() + ) + .await?; + + Ok(()) + } +}