2024-08-03 04:14:38 +02:00
|
|
|
use crate::{
|
2025-02-03 11:34:22 +01:00
|
|
|
activities::{create_post::CreatePost, follow::Follow}, entities::{
|
2024-08-03 04:14:38 +02:00
|
|
|
self, follow_relation,
|
|
|
|
|
prelude::{self, FollowRelation},
|
|
|
|
|
user,
|
2025-02-03 11:34:22 +01:00
|
|
|
}, utils::generate_follow_req_id, versia::http::main_versia_url_to_user_and_model, API_DOMAIN, DB, FEDERATION_CONFIG
|
2024-08-03 04:14:38 +02:00
|
|
|
};
|
|
|
|
|
use activitypub_federation::{
|
|
|
|
|
activity_sending::SendActivityTask, fetch::object_id::ObjectId, protocol::context::WithContext,
|
|
|
|
|
};
|
2025-02-03 11:34:22 +01:00
|
|
|
use activitystreams_kinds::{activity::FollowType, public};
|
2024-08-03 03:49:07 +02:00
|
|
|
use anyhow::Result;
|
|
|
|
|
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityOrSelect, EntityTrait, QueryFilter, Set};
|
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
use url::Url;
|
|
|
|
|
|
2024-08-03 04:14:38 +02:00
|
|
|
use super::{
|
2025-02-03 13:56:29 +01:00
|
|
|
conversion::{db_user_from_url, fetch_user_from_url, receive_versia_note, versia_user_from_db},
|
2024-08-28 15:24:22 +02:00
|
|
|
http::{versia_url_to_user, versia_url_to_user_and_model},
|
2024-08-03 04:14:38 +02:00
|
|
|
};
|
2024-08-03 03:49:07 +02:00
|
|
|
|
|
|
|
|
pub async fn inbox_entry(json: &str) -> Result<()> {
|
|
|
|
|
// Deserialize the JSON string into a dynamic value
|
|
|
|
|
let value: serde_json::Value = serde_json::from_str(json).unwrap();
|
|
|
|
|
|
|
|
|
|
// Extract the "type" field from the JSON
|
|
|
|
|
if let Some(json_type) = value.get("type") {
|
2024-08-28 15:24:22 +02:00
|
|
|
// Match the "type" field with the corresponding VersiaType
|
2024-08-03 03:49:07 +02:00
|
|
|
match json_type.as_str() {
|
|
|
|
|
Some("Note") => {
|
|
|
|
|
let note: super::objects::Note = serde_json::from_str(json)?;
|
2024-11-22 22:08:25 +01:00
|
|
|
federate_inbox(note).await?;
|
2024-08-03 03:49:07 +02:00
|
|
|
}
|
|
|
|
|
Some("Follow") => {
|
|
|
|
|
let follow_req: super::objects::Follow = serde_json::from_str(json)?;
|
2024-08-03 06:25:16 +02:00
|
|
|
follow_request(follow_req).await?;
|
2024-08-03 03:49:07 +02:00
|
|
|
}
|
|
|
|
|
Some("FollowAccept") => {
|
|
|
|
|
let follow_accept: super::objects::FollowResult = serde_json::from_str(json)?;
|
|
|
|
|
}
|
|
|
|
|
Some("FollowReject") => {
|
|
|
|
|
let follow_rej: super::objects::FollowResult = serde_json::from_str(json)?;
|
|
|
|
|
}
|
2024-11-19 22:15:19 +01:00
|
|
|
Some("Unfollow") => {
|
|
|
|
|
let unfollow: super::objects::Unfollow = serde_json::from_str(json)?;
|
|
|
|
|
}
|
2024-08-03 03:49:07 +02:00
|
|
|
// Add more cases for other types as needed
|
|
|
|
|
_ => {
|
2024-08-03 04:14:38 +02:00
|
|
|
return Err(anyhow::anyhow!(
|
|
|
|
|
"Unknown 'type' field in JSON, it is {}",
|
|
|
|
|
json_type
|
|
|
|
|
));
|
2024-08-03 03:49:07 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return Err(anyhow::anyhow!("Missing 'type' field in JSON"));
|
|
|
|
|
}
|
|
|
|
|
Ok(())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async fn follow_request(follow: super::objects::Follow) -> Result<()> {
|
|
|
|
|
// Check if the user is already following the requester
|
|
|
|
|
let db = DB.get().unwrap();
|
|
|
|
|
let query = FollowRelation::find()
|
|
|
|
|
.filter(follow_relation::Column::FollowerId.eq(follow.author.to_string().as_str()))
|
|
|
|
|
.filter(follow_relation::Column::FolloweeId.eq(follow.followee.to_string().as_str()))
|
|
|
|
|
.one(db)
|
|
|
|
|
.await?;
|
|
|
|
|
if query.is_some() {
|
2024-08-03 04:14:38 +02:00
|
|
|
return Err(anyhow::anyhow!(
|
|
|
|
|
"User is already follow requesting / following the followee"
|
|
|
|
|
));
|
2024-08-03 03:49:07 +02:00
|
|
|
}
|
|
|
|
|
let data = FEDERATION_CONFIG.get().unwrap();
|
2024-08-28 15:24:22 +02:00
|
|
|
let author = main_versia_url_to_user_and_model(follow.author.into()).await?;
|
2024-08-03 15:30:34 +02:00
|
|
|
println!("Followee URL: {}", &follow.followee.to_string());
|
2024-08-28 15:24:22 +02:00
|
|
|
let followee = versia_url_to_user_and_model(follow.followee.into()).await?;
|
2024-08-03 04:14:38 +02:00
|
|
|
let serial_ap_author = serde_json::from_str::<crate::objects::person::Person>(
|
|
|
|
|
&(author.1.ap_json.clone()).unwrap(),
|
|
|
|
|
)?;
|
|
|
|
|
let serial_ap_followee = serde_json::from_str::<crate::objects::person::Person>(
|
|
|
|
|
&(followee.1.ap_json.clone()).unwrap(),
|
|
|
|
|
)?;
|
2024-08-03 03:49:07 +02:00
|
|
|
|
|
|
|
|
let id = uuid::Uuid::now_v7().to_string();
|
|
|
|
|
|
2024-08-03 10:19:20 +02:00
|
|
|
let followee_object: ObjectId<user::Model> = serial_ap_followee.id;
|
|
|
|
|
let localuser_object: ObjectId<user::Model> = serial_ap_author.id;
|
2024-08-03 03:49:07 +02:00
|
|
|
|
2024-08-03 04:14:38 +02:00
|
|
|
println!(
|
|
|
|
|
"Sending follow request to {}",
|
|
|
|
|
&followee.0.display_name.unwrap_or(followee.0.username)
|
|
|
|
|
);
|
2024-08-03 03:49:07 +02:00
|
|
|
let create = Follow {
|
|
|
|
|
actor: localuser_object.clone(),
|
|
|
|
|
object: followee_object.clone(),
|
|
|
|
|
kind: FollowType::Follow,
|
2024-08-03 08:23:46 +02:00
|
|
|
id: generate_follow_req_id(&API_DOMAIN.to_string(), id.clone().as_str())?,
|
2024-08-03 03:49:07 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let ap_json = serde_json::to_string(&create)?;
|
|
|
|
|
|
|
|
|
|
let create_with_context = WithContext::new_default(create);
|
|
|
|
|
|
|
|
|
|
let follow_db_entry = follow_relation::ActiveModel {
|
|
|
|
|
id: Set(id.clone()),
|
|
|
|
|
followee_id: Set(followee.0.id.to_string()),
|
|
|
|
|
follower_id: Set(author.0.id.to_string()),
|
|
|
|
|
ap_id: Set(Some(id.clone())),
|
|
|
|
|
ap_json: Set(ap_json),
|
|
|
|
|
remote: Set(false),
|
|
|
|
|
..Default::default()
|
|
|
|
|
};
|
|
|
|
|
follow_db_entry.insert(db).await?;
|
|
|
|
|
|
|
|
|
|
let sends = SendActivityTask::prepare(
|
|
|
|
|
&create_with_context,
|
2024-08-03 08:10:22 +02:00
|
|
|
&author.1,
|
2024-08-03 03:49:07 +02:00
|
|
|
vec![serial_ap_followee.inbox],
|
|
|
|
|
&data.to_request_data(),
|
|
|
|
|
)
|
|
|
|
|
.await?;
|
|
|
|
|
|
|
|
|
|
for send in sends {
|
|
|
|
|
send.sign_and_send(&data.to_request_data()).await?;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Ok(())
|
2024-08-03 04:14:38 +02:00
|
|
|
}
|
2024-11-22 22:08:25 +01:00
|
|
|
|
|
|
|
|
async fn federate_inbox(note: super::objects::Note) -> Result<()> {
|
2025-02-03 11:34:22 +01:00
|
|
|
let db_user = db_user_from_url(note.author.clone()).await?;
|
|
|
|
|
let note = receive_versia_note(note, db_user.id).await?;
|
|
|
|
|
|
|
|
|
|
let ap_str = note.ap_json.clone().unwrap();
|
|
|
|
|
let ap_note = serde_json::from_str::<crate::objects::post::Note>(&ap_str)?;
|
|
|
|
|
|
|
|
|
|
tokio::spawn(async move {
|
|
|
|
|
let conf = FEDERATION_CONFIG.get().unwrap();
|
2025-02-03 13:56:29 +01:00
|
|
|
let inbox = get_inbox_vec(&ap_note).await;
|
2025-02-03 11:34:22 +01:00
|
|
|
|
|
|
|
|
let res = CreatePost::sends(ap_note, note, inbox, &conf.to_request_data()).await;
|
|
|
|
|
if let Err(e) = res {
|
|
|
|
|
panic!("Problem federating: {e:?}");
|
|
|
|
|
}
|
|
|
|
|
});
|
2024-11-22 22:08:25 +01:00
|
|
|
|
|
|
|
|
Ok(())
|
2025-02-03 11:34:22 +01:00
|
|
|
}
|
|
|
|
|
|
2025-02-03 13:56:29 +01:00
|
|
|
async fn get_inbox_vec(ap_note: &crate::objects::post::Note) -> Vec<Url> {
|
|
|
|
|
let mut inbox_users: Vec<Url> = Vec::new();
|
2025-02-03 11:34:22 +01:00
|
|
|
let mut inbox: Vec<Url> = Vec::new();
|
|
|
|
|
|
2025-02-03 14:00:28 +01:00
|
|
|
let entry = ap_note.to.get(0).unwrap();
|
|
|
|
|
if entry.to_string().eq_ignore_ascii_case(public().to_string().as_str()) {
|
|
|
|
|
let (_, mentions) = ap_note.to.split_at(2);
|
|
|
|
|
inbox_users.append(&mut mentions.to_vec());
|
|
|
|
|
} else {
|
|
|
|
|
let (_, mentions) = ap_note.to.split_at(1);
|
|
|
|
|
inbox_users.append(&mut mentions.to_vec());
|
2025-02-03 11:34:22 +01:00
|
|
|
}
|
|
|
|
|
|
2025-02-03 13:56:29 +01:00
|
|
|
inbox_users.dedup();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let conf = FEDERATION_CONFIG.get().unwrap();
|
|
|
|
|
let data = &conf.to_request_data();
|
|
|
|
|
|
|
|
|
|
for user in inbox_users {
|
|
|
|
|
let ap_user = ObjectId::<user::Model>::from(user).dereference(data)
|
|
|
|
|
.await.unwrap();
|
|
|
|
|
inbox.push(Url::parse(&ap_user.inbox).unwrap());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
inbox.dedup();
|
|
|
|
|
|
2025-02-03 11:34:22 +01:00
|
|
|
inbox
|
2024-11-22 22:08:25 +01:00
|
|
|
}
|