save changes, fake commit

This commit is contained in:
April John 2024-05-19 07:17:13 +02:00
parent b65a51a1ef
commit e42baf51e4
Signed by: aprl
GPG key ID: BCB934A2909C5460
8 changed files with 88 additions and 45 deletions

View file

@ -1,8 +1,5 @@
use crate::{ use crate::{
database::StateHandle, database::StateHandle, entities::user, error::Error, lysand::{self, conversion::receive_lysand_note}, objects::person::{DbUser, PersonAcceptedActivities}
entities::user,
error::Error,
objects::person::{DbUser, PersonAcceptedActivities},
}; };
use activitypub_federation::{ use activitypub_federation::{
actix_web::{inbox::receive_activity, signing_actor}, actix_web::{inbox::receive_activity, signing_actor},
@ -36,6 +33,11 @@ pub fn listen(config: &FederationConfig<StateHandle>) -> Result<(), Error> {
Ok(()) Ok(())
} }
pub fn lysand_inbox(note: web::Json<lysand::objects::Note>, id: web::Path<String>, data: Data<StateHandle>) -> Result<HttpResponse, Error> {
tokio::spawn(receive_lysand_note(note.into_inner(), id.into_inner(), data.app_data().clone()));
Ok(HttpResponse::Created().finish())
}
/// Handles requests to fetch system user json over HTTP /// Handles requests to fetch system user json over HTTP
/*pub async fn http_get_system_user(data: Data<DatabaseHandle>) -> Result<HttpResponse, Error> { /*pub async fn http_get_system_user(data: Data<DatabaseHandle>) -> Result<HttpResponse, Error> {
let json_user = data.system_user.clone().into_json(&data).await?; let json_user = data.system_user.clone().into_json(&data).await?;

46
src/lysand/conversion.rs Normal file
View file

@ -0,0 +1,46 @@
use activitypub_federation::fetch::object_id::ObjectId;
use activitystreams_kinds::public;
use sea_orm::{EntityTrait, QueryFilter};
use url::Url;
use crate::{database::State, entities::{self, post, prelude}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, FEDERATION_CONFIG};
use super::objects::Note;
pub async fn receive_lysand_note(note: Note, db_id: String, db: State) {
let author: entities::user::Model = todo!();
let user_res = prelude::User::find_by_id(db_id).one(db.database_connection.as_ref()).await;
if user_res.is_err() {
println!("{}", user_res.unwrap_err());
return;
}
if let Some(target) = user_res.ok().unwrap() {
let data = FEDERATION_CONFIG.get().unwrap();
let id: ObjectId<post::Model> = generate_object_id(data.domain(), &note.id.to_string()).unwrap().into();
let user_id = generate_user_id(data.domain(), &target.id.to_string()).unwrap();
let to = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) {
super::objects::VisibilityType::Public => vec![public(), Url::parse(&author.inbox).unwrap()],
super::objects::VisibilityType::Followers => vec![Url::parse(&author.inbox).unwrap()],
super::objects::VisibilityType::Direct => vec![user_id],
super::objects::VisibilityType::Unlisted => vec![Url::parse(&author.inbox).unwrap()],
};
let cc = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) {
super::objects::VisibilityType::Unlisted => Some(vec![public()]),
_ => None
};
let mut tag: Vec<Mention> = Vec::new();
for l_tag in note.mentions.unwrap_or_default() {
tag.push(Mention { href: l_tag, //todo convert to ap url
kind: Default::default(), })
}
let ap_note = crate::objects::post::Note {
kind: Default::default(),
id,
sensitive: note.is_sensitive.unwrap_or(false),
cc,
to,
tag,
}
}
}

View file

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

View file

@ -58,7 +58,7 @@ pub enum CategoryType {
Image, Image,
Video, Video,
Audio, Audio,
Messaging Messaging,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
@ -66,7 +66,7 @@ pub enum VisibilityType {
Public, Public,
Unlisted, Unlisted,
Followers, Followers,
Direct Direct,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
@ -191,7 +191,7 @@ pub struct LinkPreview {
title: String, title: String,
link: Url, link: Url,
image: Option<Url>, image: Option<Url>,
icon: Option<Url> icon: Option<Url>,
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]

View file

@ -22,10 +22,7 @@ pub async fn main() -> anyhow::Result<()> {
let user_json = serde_json::to_string_pretty(&SortAlphabetically(&user))?; let user_json = serde_json::to_string_pretty(&SortAlphabetically(&user))?;
println!("{}", user_json); println!("{}", user_json);
let response_outbox = client let response_outbox = client.get(user.outbox.as_str()).send().await?;
.get(user.outbox.as_str())
.send()
.await?;
let outbox_json = response_outbox.text().await?; let outbox_json = response_outbox.text().await?;
let outbox = super::superx::deserialize_outbox(outbox_json).await?; let outbox = super::superx::deserialize_outbox(outbox_json).await?;

View file

@ -76,12 +76,12 @@ async fn post_manually(
) -> actix_web::Result<HttpResponse, error::Error> { ) -> actix_web::Result<HttpResponse, error::Error> {
let local_user = state.local_user().await?; let local_user = state.local_user().await?;
let data = FEDERATION_CONFIG.get().unwrap(); let data = FEDERATION_CONFIG.get().unwrap();
let creator = let target =
webfinger_resolve_actor::<State, user::Model>(path.0.as_str(), &data.to_request_data()) webfinger_resolve_actor::<State, user::Model>(path.0.as_str(), &data.to_request_data())
.await?; .await?;
let mention = Mention { let mention = Mention {
href: Url::parse(&creator.id)?, href: Url::parse(&target.id)?,
kind: Default::default(), kind: Default::default(),
}; };
let id: ObjectId<post::Model> = generate_object_id(data.domain())?.into(); let id: ObjectId<post::Model> = generate_object_id(data.domain())?.into();
@ -89,16 +89,16 @@ async fn post_manually(
kind: Default::default(), kind: Default::default(),
id, id,
sensitive: false, sensitive: false,
attributed_to: Url::parse(&data.local_user().await?.id).unwrap().into(), attributed_to: Url::parse(&local_user.id).unwrap().into(),
to: vec![public()], to: vec![public()],
content: format!("{} {}", path.1, creator.name), content: format!("{} {}", path.1, target.name),
tag: vec![mention], tag: vec![mention],
in_reply_to: None, in_reply_to: None,
}; };
CreatePost::send( CreatePost::send(
note, note,
creator.shared_inbox_or_inbox(), target.shared_inbox_or_inbox(),
&data.to_request_data(), &data.to_request_data(),
) )
.await?; .await?;
@ -131,16 +131,18 @@ async fn follow_manually(
Ok(HttpResponse::Ok().json(Response { health: true })) Ok(HttpResponse::Ok().json(Response { health: true }))
} }
const DOMAIN_DEF: &str = "example.com"; const DOMAIN_DEF: &str = "social.lysand.org";
const LOCAL_USER_NAME: &str = "example"; const LOCAL_USER_NAME: &str = "example";
lazy_static! { lazy_static! {
static ref SERVER_URL: String = env::var("LISTEN").unwrap_or("127.0.0.1:8080".to_string()); static ref SERVER_URL: String = env::var("LISTEN").unwrap_or("0.0.0.0:8080".to_string());
static ref DATABASE_URL: String = env::var("DATABASE_URL").expect("DATABASE_URL must be set"); static ref DATABASE_URL: String = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
static ref USERNAME: String = static ref USERNAME: String =
env::var("LOCAL_USER_NAME").unwrap_or(LOCAL_USER_NAME.to_string()); env::var("LOCAL_USER_NAME").unwrap_or(LOCAL_USER_NAME.to_string());
static ref API_DOMAIN: String = env::var("API_DOMAIN").unwrap_or(DOMAIN_DEF.to_string()); static ref API_DOMAIN: String = env::var("API_DOMAIN").expect("not set API_DOMAIN");
static ref FEDERATED_DOMAIN: String = env::var("FEDERATED_DOMAIN").unwrap_or(DOMAIN_DEF.to_string()); static ref LYSAND_DOMAIN: String = env::var("LYSAND_DOMAIN").expect("not set LYSAND_DOMAIN");
static ref FEDERATED_DOMAIN: String =
env::var("FEDERATED_DOMAIN").unwrap_or(API_DOMAIN.to_string());
} }
static DB: OnceLock<DatabaseConnection> = OnceLock::new(); static DB: OnceLock<DatabaseConnection> = OnceLock::new();
@ -204,7 +206,7 @@ async fn main() -> actix_web::Result<(), anyhow::Error> {
}; };
let data = FederationConfig::builder() let data = FederationConfig::builder()
.domain(env::var("FEDERATED_DOMAIN").expect("FEDERATED_DOMAIN must be set")) .domain(FEDERATED_DOMAIN.to_string())
.app_data(state.clone()) .app_data(state.clone())
.http_signature_compat(true) .http_signature_compat(true)
.signed_fetch_actor(&state.local_user().await.unwrap()) .signed_fetch_actor(&state.local_user().await.unwrap())
@ -214,18 +216,9 @@ async fn main() -> actix_web::Result<(), anyhow::Error> {
let _ = FEDERATION_CONFIG.set(data.clone()); let _ = FEDERATION_CONFIG.set(data.clone());
let mut labels = HashMap::new(); let mut labels = HashMap::new();
labels.insert( labels.insert("domain".to_string(), FEDERATED_DOMAIN.to_string());
"domain".to_string(), labels.insert("name".to_string(), USERNAME.to_string());
env::var("FEDERATED_DOMAIN") labels.insert("api_domain".to_string(), API_DOMAIN.to_string());
.expect("FEDERATED_DOMAIN must be set")
.to_string(),
);
labels.insert(
"name".to_string(),
env::var("LOCAL_USER_NAME")
.expect("LOCAL_USER_NAME must be set")
.to_string(),
);
let prometheus = PrometheusMetricsBuilder::new("api") let prometheus = PrometheusMetricsBuilder::new("api")
.endpoint("/metrics") .endpoint("/metrics")

View file

@ -40,6 +40,7 @@ pub struct Note {
pub(crate) in_reply_to: Option<ObjectId<post::Model>>, pub(crate) in_reply_to: Option<ObjectId<post::Model>>,
pub(crate) tag: Vec<Mention>, pub(crate) tag: Vec<Mention>,
pub(crate) sensitive: bool, pub(crate) sensitive: bool,
pub(crate) cc: Option<Vec<Url>>,
} }
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]

View file

@ -1,18 +1,21 @@
use rand::{distributions::Alphanumeric, thread_rng, Rng};
use url::{ParseError, Url}; use url::{ParseError, Url};
/// Just generate random url as object id. In a real project, you probably want to use pub fn generate_object_id(domain: &str, uuid: &str) -> Result<Url, ParseError> {
/// an url which contains the database id for easy retrieval (or store the random id in db). let id: String = uuid::Uuid::new_v4().to_string();
pub fn generate_object_id(domain: &str) -> Result<Url, ParseError> { Url::parse(&format!("https://{}/apbridge/object/{}", domain, id))
let id: String = thread_rng() }
.sample_iter(&Alphanumeric)
.take(7) pub fn generate_user_id(domain: &str, uuid: &str) -> Result<Url, ParseError> {
.map(char::from) let id: String = uuid::Uuid::new_v4().to_string();
.collect(); Url::parse(&format!("https://{}/apbridge/user/{}", domain, id))
Url::parse(&format!("https://{}/objects/{}", domain, id)) }
pub fn generate_random_object_id(domain: &str) -> Result<Url, ParseError> {
let id: String = uuid::Uuid::new_v4().to_string();
Url::parse(&format!("https://{}/apbridge/object/{}", domain, id))
} }
/// Generate a follow accept id /// Generate a follow accept id
pub fn generate_follow_accept_id(domain: &str, db_id: i32) -> Result<Url, ParseError> { pub fn generate_follow_accept_id(domain: &str, db_id: i32) -> Result<Url, ParseError> {
Url::parse(&format!("https://{}/activities/follow/{}", domain, db_id)) Url::parse(&format!("https://{}/apbridge/activity/follow/{}", domain, db_id))
} }