feat: process and store fields and aliases
basically moved_to, also_known_as and actor attachments
This commit is contained in:
parent
f115ab67b8
commit
e0f427a2b9
6 changed files with 81 additions and 2 deletions
|
@ -34,6 +34,6 @@ tracing = "0.1"
|
||||||
tokio = { version = "1.35", features = ["full"] } # TODO slim this down
|
tokio = { version = "1.35", features = ["full"] } # TODO slim this down
|
||||||
sea-orm = { version = "0.12", features = ["macros", "sqlx-sqlite", "sqlx-postgres", "runtime-tokio-rustls"] }
|
sea-orm = { version = "0.12", features = ["macros", "sqlx-sqlite", "sqlx-postgres", "runtime-tokio-rustls"] }
|
||||||
reqwest = { version = "0.12", features = ["json"] }
|
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 = "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" }
|
nodeinfo = { git = "https://codeberg.org/thefederationinfo/nodeinfo-rs", rev = "e865094804" }
|
||||||
|
|
|
@ -1,6 +1,27 @@
|
||||||
use sea_orm::{entity::prelude::*, QuerySelect, SelectColumns};
|
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<ChronoDateTimeUtc>,
|
||||||
|
|
||||||
|
#[serde(rename = "type")]
|
||||||
|
pub field_type: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: apb::Object> From<T> 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)]
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
|
||||||
#[sea_orm(table_name = "actors")]
|
#[sea_orm(table_name = "actors")]
|
||||||
|
@ -16,6 +37,7 @@ pub struct Model {
|
||||||
pub image: Option<String>,
|
pub image: Option<String>,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<String>,
|
||||||
pub preferred_username: String,
|
pub preferred_username: String,
|
||||||
|
pub fields: Vec<Field>,
|
||||||
pub inbox: Option<String>,
|
pub inbox: Option<String>,
|
||||||
pub shared_inbox: Option<String>,
|
pub shared_inbox: Option<String>,
|
||||||
pub outbox: Option<String>,
|
pub outbox: Option<String>,
|
||||||
|
@ -28,6 +50,8 @@ pub struct Model {
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub published: ChronoDateTimeUtc,
|
pub published: ChronoDateTimeUtc,
|
||||||
pub updated: ChronoDateTimeUtc,
|
pub updated: ChronoDateTimeUtc,
|
||||||
|
pub also_known_as: Vec<String>,
|
||||||
|
pub moved_to: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
|
||||||
|
@ -183,6 +207,12 @@ impl Model {
|
||||||
.set_document_type(Some(apb::DocumentType::Image))
|
.set_document_type(Some(apb::DocumentType::Image))
|
||||||
.set_url(apb::Node::link(i.clone()))
|
.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_published(Some(self.published))
|
||||||
.set_updated(if self.updated != self.published { Some(self.updated) } else { None })
|
.set_updated(if self.updated != self.published { Some(self.updated) } else { None })
|
||||||
.set_preferred_username(Some(&self.preferred_username))
|
.set_preferred_username(Some(&self.preferred_username))
|
||||||
|
@ -203,6 +233,8 @@ impl Model {
|
||||||
apb::new()
|
apb::new()
|
||||||
.set_shared_inbox(self.shared_inbox.as_deref())
|
.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))
|
.set_discoverable(Some(true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -333,11 +333,14 @@ impl AP {
|
||||||
summary: actor.summary().str(),
|
summary: actor.summary().str(),
|
||||||
icon: actor.icon().get().and_then(|x| x.url().id().str()),
|
icon: actor.icon().get().and_then(|x| x.url().id().str()),
|
||||||
image: actor.image().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(),
|
inbox: actor.inbox().id().str(),
|
||||||
outbox: actor.outbox().id().str(),
|
outbox: actor.outbox().id().str(),
|
||||||
shared_inbox: actor.endpoints().get().and_then(|x| x.shared_inbox().str()),
|
shared_inbox: actor.endpoints().get().and_then(|x| x.shared_inbox().str()),
|
||||||
followers: actor.followers().id().str(),
|
followers: actor.followers().id().str(),
|
||||||
following: actor.following().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()),
|
published: actor.published().unwrap_or(chrono::Utc::now()),
|
||||||
updated: chrono::Utc::now(),
|
updated: chrono::Utc::now(),
|
||||||
following_count: actor.following_count().unwrap_or(0) as i32,
|
following_count: actor.following_count().unwrap_or(0) as i32,
|
||||||
|
|
|
@ -18,6 +18,7 @@ mod m20240703_000001_add_audience_index;
|
||||||
mod m20240703_000002_add_image_to_objects;
|
mod m20240703_000002_add_image_to_objects;
|
||||||
mod m20240706_000001_add_error_to_jobs;
|
mod m20240706_000001_add_error_to_jobs;
|
||||||
mod m20240715_000001_add_quote_uri_to_objects;
|
mod m20240715_000001_add_quote_uri_to_objects;
|
||||||
|
mod m20240715_000002_add_actors_fields_and_aliases;
|
||||||
|
|
||||||
pub struct Migrator;
|
pub struct Migrator;
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ impl MigratorTrait for Migrator {
|
||||||
Box::new(m20240703_000002_add_image_to_objects::Migration),
|
Box::new(m20240703_000002_add_image_to_objects::Migration),
|
||||||
Box::new(m20240706_000001_add_error_to_jobs::Migration),
|
Box::new(m20240706_000001_add_error_to_jobs::Migration),
|
||||||
Box::new(m20240715_000001_add_quote_uri_to_objects::Migration),
|
Box::new(m20240715_000001_add_quote_uri_to_objects::Migration),
|
||||||
|
Box::new(m20240715_000002_add_actors_fields_and_aliases::Migration),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ pub enum Actors {
|
||||||
Image,
|
Image,
|
||||||
Icon,
|
Icon,
|
||||||
PreferredUsername,
|
PreferredUsername,
|
||||||
|
Fields, // added with migration m20240715_000002
|
||||||
Inbox,
|
Inbox,
|
||||||
SharedInbox,
|
SharedInbox,
|
||||||
Outbox,
|
Outbox,
|
||||||
|
@ -22,6 +23,8 @@ pub enum Actors {
|
||||||
StatusesCount,
|
StatusesCount,
|
||||||
PublicKey,
|
PublicKey,
|
||||||
PrivateKey,
|
PrivateKey,
|
||||||
|
AlsoKnownAs, // added with migration m20240715_000002
|
||||||
|
MovedTo, // added with migration m20240715_000002
|
||||||
Published,
|
Published,
|
||||||
Updated,
|
Updated,
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<String>>(vec![]))
|
||||||
|
.add_column(ColumnDef::new(Actors::Fields).json_binary().not_null().default::<Vec<String>>(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(())
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue