mirror of
https://github.com/versia-pub/activitypub.git
synced 2025-12-06 14:48:19 +01:00
save changes, fake commit
This commit is contained in:
parent
b65a51a1ef
commit
e42baf51e4
10
src/http.rs
10
src/http.rs
|
|
@ -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
46
src/lysand/conversion.rs
Normal 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(), ¬e.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,
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -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)]
|
||||||
|
|
|
||||||
|
|
@ -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?;
|
||||||
|
|
|
||||||
37
src/main.rs
37
src/main.rs
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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)]
|
||||||
|
|
|
||||||
25
src/utils.rs
25
src/utils.rs
|
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue