mirror of
https://github.com/versia-pub/activitypub.git
synced 2026-03-13 10:59:17 +01:00
[feat]: lysand to ap for posts and users
This commit is contained in:
parent
bcab516a1f
commit
1174f92915
11 changed files with 151 additions and 39 deletions
|
|
@ -1,8 +1,8 @@
|
|||
use activitypub_federation::{fetch::object_id::ObjectId, http_signatures::generate_actor_keypair};
|
||||
use activitystreams_kinds::public;
|
||||
use chrono::{DateTime, Utc};
|
||||
use chrono::{DateTime, TimeZone, Utc};
|
||||
use sea_orm::{ActiveModelTrait, ColumnTrait, EntityTrait, QueryFilter, Set};
|
||||
use anyhow::anyhow;
|
||||
use anyhow::{anyhow, Ok};
|
||||
use url::Url;
|
||||
|
||||
use crate::{database::State, entities::{self, post, prelude, user}, objects::post::Mention, utils::{generate_object_id, generate_user_id}, API_DOMAIN, DB, FEDERATION_CONFIG, LYSAND_DOMAIN};
|
||||
|
|
@ -27,7 +27,7 @@ pub async fn db_user_from_url(url: Url) -> anyhow::Result<entities::user::Model>
|
|||
if !url.domain().eq(&Some(LYSAND_DOMAIN.as_str())) {
|
||||
return Err(anyhow!("not lysands domain"));
|
||||
}
|
||||
let user_res = prelude::User::find().filter(entities::user::Column::Url.eq(url.to_string())).one(DB.get().unwrap()).await?;
|
||||
let user_res: Option<user::Model> = prelude::User::find().filter(entities::user::Column::Url.eq(url.to_string())).one(DB.get().unwrap()).await?;
|
||||
|
||||
if let Some(user) = user_res {
|
||||
Ok(user)
|
||||
|
|
@ -64,8 +64,8 @@ pub async fn fetch_note_from_url(url: Url) -> anyhow::Result<super::objects::Not
|
|||
Ok(request.json::<super::objects::Note>().await?)
|
||||
}
|
||||
|
||||
pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<()> {
|
||||
let author: entities::user::Model = db_user_from_url(note.author.clone()).await?;
|
||||
pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<crate::objects::post::Note> {
|
||||
let lysand_author: entities::user::Model = db_user_from_url(note.author.clone()).await?;
|
||||
let user_res = prelude::User::find_by_id(db_id).one(DB.get().unwrap()).await;
|
||||
if user_res.is_err() {
|
||||
println!("{}", user_res.as_ref().unwrap_err());
|
||||
|
|
@ -75,23 +75,45 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<()
|
|||
let data = FEDERATION_CONFIG.get().unwrap();
|
||||
let id: ObjectId<post::Model> = generate_object_id(data.domain(), ¬e.id.to_string())?.into();
|
||||
let user_id = generate_user_id(data.domain(), &target.id.to_string())?;
|
||||
let user = fetch_user_from_url(user_id).await?;
|
||||
let user = fetch_user_from_url(note.author.clone()).await?;
|
||||
let mut tag: Vec<Mention> = Vec::new();
|
||||
for l_tag in note.mentions.clone().unwrap_or_default() {
|
||||
tag.push(Mention { href: l_tag, //todo convert to ap url
|
||||
tag.push(Mention { href: l_tag, //TODO convert to ap url
|
||||
kind: Default::default(), })
|
||||
}
|
||||
let to = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) {
|
||||
super::objects::VisibilityType::Public => vec![public(), Url::parse(&author.followers.unwrap_or_default())?],
|
||||
super::objects::VisibilityType::Followers => vec![Url::parse(&author.followers.unwrap_or_default())?],
|
||||
super::objects::VisibilityType::Public => vec![public(), Url::parse(&user.followers.to_string().as_str())?],
|
||||
super::objects::VisibilityType::Followers => vec![Url::parse(&user.followers.to_string().as_str())?],
|
||||
super::objects::VisibilityType::Direct => note.mentions.unwrap_or_default(),
|
||||
super::objects::VisibilityType::Unlisted => vec![Url::parse(&author.followers.unwrap_or_default())?],
|
||||
super::objects::VisibilityType::Unlisted => vec![Url::parse(&user.followers.to_string().as_str())?],
|
||||
};
|
||||
let cc = match note.visibility.unwrap_or(super::objects::VisibilityType::Public) {
|
||||
let cc = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) {
|
||||
super::objects::VisibilityType::Unlisted => Some(vec![public()]),
|
||||
_ => None
|
||||
};
|
||||
let reply: Option<ObjectId<entities::post::Model>> = if let Some(rep) = note.replies_to {
|
||||
let reply: Option<ObjectId<entities::post::Model>> = if let Some(rep) = note.replies_to.clone() {
|
||||
let note = fetch_note_from_url(rep).await?;
|
||||
let fake_rep_url = Url::parse(&format!(
|
||||
"https://{}/lysand/apnote/{}",
|
||||
API_DOMAIN.to_string(),
|
||||
¬e.id.to_string()
|
||||
))?;
|
||||
Some(fake_rep_url.into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let reply_string: Option<String> = if let Some(rep) = note.replies_to {
|
||||
let note = fetch_note_from_url(rep).await?;
|
||||
let fake_rep_url = Url::parse(&format!(
|
||||
"https://{}/lysand/apnote/{}",
|
||||
API_DOMAIN.to_string(),
|
||||
¬e.id.to_string()
|
||||
))?;
|
||||
Some(fake_rep_url.into())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let quote_string: Option<String> = if let Some(rep) = note.quotes.clone() {
|
||||
let note = fetch_note_from_url(rep).await?;
|
||||
let fake_rep_url = Url::parse(&format!(
|
||||
"https://{}/lysand/apnote/{}",
|
||||
|
|
@ -109,12 +131,38 @@ pub async fn receive_lysand_note(note: Note, db_id: String) -> anyhow::Result<()
|
|||
cc,
|
||||
to,
|
||||
tag,
|
||||
attributed_to: Url::parse(author.url.clone().as_str()).unwrap().into(),
|
||||
attributed_to: Url::parse(user.uri.clone().as_str()).unwrap().into(),
|
||||
content: option_content_format_text(note.content).await.unwrap_or_default(),
|
||||
in_reply_to: reply
|
||||
};
|
||||
|
||||
let visibility = match note.visibility.clone().unwrap_or(super::objects::VisibilityType::Public) {
|
||||
super::objects::VisibilityType::Public => "public",
|
||||
super::objects::VisibilityType::Followers => "followers",
|
||||
super::objects::VisibilityType::Direct => "direct",
|
||||
super::objects::VisibilityType::Unlisted => "unlisted",
|
||||
};
|
||||
|
||||
let post = entities::post::ActiveModel {
|
||||
id: Set(note.id.to_string()),
|
||||
creator: Set(lysand_author.id.clone()),
|
||||
content: Set(ap_note.content.clone()),
|
||||
sensitive: Set(ap_note.sensitive),
|
||||
created_at: Set(Utc.timestamp_micros(note.created_at.unix_timestamp()).unwrap()),
|
||||
local: Set(true),
|
||||
updated_at: Set(Some(Utc::now())),
|
||||
content_type: Set("Note".to_string()),
|
||||
visibility: Set(visibility.to_string()),
|
||||
title: Set(note.subject.clone()),
|
||||
url: Set(ap_note.id.to_string()),
|
||||
reply_id: Set(reply_string),
|
||||
quoting_id: Set(quote_string),
|
||||
spoiler_text: Set(note.subject),
|
||||
..Default::default()
|
||||
};
|
||||
post.insert(DB.get().unwrap()).await?;
|
||||
Ok(ap_note)
|
||||
} else {
|
||||
Err(anyhow!("User not found"))
|
||||
}
|
||||
|
||||
|
||||
Ok(())
|
||||
}
|
||||
0
src/lysand/funcs.rs
Normal file
0
src/lysand/funcs.rs
Normal file
24
src/lysand/http.rs
Normal file
24
src/lysand/http.rs
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
use std::os::linux::raw::stat;
|
||||
|
||||
use activitypub_federation::{traits::Object, FEDERATION_CONTENT_TYPE};
|
||||
use actix_web::{get, web, HttpResponse};
|
||||
use sea_orm::{ColumnTrait, EntityTrait, QueryFilter};
|
||||
|
||||
use crate::{database::State, entities::{post::{self, Entity}, prelude}, error, Response, DB, FEDERATION_CONFIG};
|
||||
|
||||
#[get("/apbridge/object/{post}")]
|
||||
async fn post_manually(
|
||||
path: web::Path<(String, String)>,
|
||||
state: web::Data<State>,
|
||||
) -> actix_web::Result<HttpResponse, error::Error> {
|
||||
let db = DB.get().unwrap();
|
||||
|
||||
let post = prelude::Post::find()
|
||||
.filter(post::Column::Id.eq(path.0.as_str()))
|
||||
.one(db)
|
||||
.await?;
|
||||
|
||||
let post = post.unwrap();
|
||||
|
||||
Ok(HttpResponse::Ok().content_type(FEDERATION_CONTENT_TYPE).json(post.into_json(&FEDERATION_CONFIG.get().unwrap().to_request_data()).await?))
|
||||
}
|
||||
|
|
@ -1,4 +1,6 @@
|
|||
pub mod objects;
|
||||
pub mod superx;
|
||||
pub mod test;
|
||||
pub mod conversion;
|
||||
pub mod conversion;
|
||||
pub mod funcs;
|
||||
pub mod http;
|
||||
|
|
@ -62,6 +62,7 @@ pub enum CategoryType {
|
|||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum VisibilityType {
|
||||
Public,
|
||||
Unlisted,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,19 @@ use crate::lysand::objects::SortAlphabetically;
|
|||
|
||||
use super::superx::request_client;
|
||||
|
||||
#[actix_web::test]
|
||||
async fn test_user_serial() {
|
||||
let client = request_client();
|
||||
let response = client
|
||||
.get("https://social.lysand.org/users/018ec082-0ae1-761c-b2c5-22275a611771")
|
||||
.send()
|
||||
.await.unwrap();
|
||||
let user = super::superx::deserialize_user(response.text().await.unwrap()).await.unwrap();
|
||||
let response_outbox = client.get(user.outbox.as_str()).send().await.unwrap();
|
||||
let outbox = super::superx::deserialize_outbox(response_outbox.text().await.unwrap()).await.unwrap();
|
||||
assert!(outbox.items.len() > 0);
|
||||
}
|
||||
|
||||
pub async fn main() -> anyhow::Result<()> {
|
||||
let client = request_client();
|
||||
|
||||
|
|
@ -30,5 +43,13 @@ pub async fn main() -> anyhow::Result<()> {
|
|||
println!("\n\n\nOutbox: ");
|
||||
print!("{:#?}", outbox);
|
||||
|
||||
println!("\n\n\nas AP:");
|
||||
for item in outbox.items {
|
||||
let ap_item = super::conversion::receive_lysand_note(item, "https://ap.lysand.org/example".to_string()).await?;
|
||||
println!("{:#?}", ap_item);
|
||||
let ap_json = serde_json::to_string_pretty(&SortAlphabetically(&ap_item))?;
|
||||
println!("{}", ap_json);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue