use crate::{ activities::create_post::CreatePost, database::StateHandle, entities::{post, user}, error::Error, objects::person::DbUser, utils::generate_object_id, }; use activitypub_federation::{ config::Data, fetch::object_id::ObjectId, kinds::{object::NoteType, public}, protocol::{helpers::deserialize_one_or_many, verification::verify_domains_match}, traits::{Actor, Object}, }; use activitystreams_kinds::link::MentionType; use sea_orm::{ActiveModelTrait, Set}; use serde::{Deserialize, Serialize}; use tracing::info; use url::Url; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct DbPost { pub text: String, pub ap_id: ObjectId, pub creator: ObjectId, pub local: bool, } #[derive(Deserialize, Serialize, Debug)] #[serde(rename_all = "camelCase")] pub struct Note { #[serde(rename = "type")] pub(crate) kind: NoteType, pub(crate) id: ObjectId, pub(crate) attributed_to: ObjectId, #[serde(deserialize_with = "deserialize_one_or_many")] pub(crate) to: Vec, pub(crate) content: String, pub(crate) in_reply_to: Option>, pub(crate) tag: Vec, pub(crate) sensitive: bool, pub(crate) cc: Option>, } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Mention { pub href: Url, #[serde(rename = "type")] pub kind: MentionType, } #[async_trait::async_trait] impl Object for post::Model { type DataType = StateHandle; type Kind = Note; type Error = Error; async fn read_from_id( _object_id: Url, _data: &Data, ) -> Result, Self::Error> { Ok(None) } async fn into_json(self, _data: &Data) -> Result { todo!() } async fn verify( json: &Self::Kind, expected_domain: &Url, _data: &Data, ) -> Result<(), Self::Error> { verify_domains_match(json.id.inner(), expected_domain)?; Ok(()) } async fn from_json(json: Self::Kind, data: &Data) -> Result { println!( "Received post with content {} and id {}", &json.content, &json.id ); let creator = json.attributed_to.dereference(data).await?; let post: post::ActiveModel = post::ActiveModel { content: Set(json.content.clone()), id: Set(json.id.to_string()), creator: Set(creator.id.to_string()), created_at: Set(chrono::Utc::now()), //TODO: make this use the real timestamp content_type: Set("text/plain".to_string()), // TODO: make this use the real content type local: Set(false), visibility: Set("public".to_string()), // TODO: make this use the real visibility sensitive: Set(json.sensitive.clone()), url: Set(json.id.clone().to_string()), ..Default::default() }; let post = post .insert(data.app_data().database_connection.clone().as_ref()) .await; if let Err(err) = post { eprintln!("Error inserting post: {:?}", err); return Err(err.into()); } info!("Post inserted: {:?}", post.as_ref().unwrap()); Ok(post.unwrap()) } }