ferri/ferri-server/src/endpoints/custom.rs

124 lines
3.2 KiB
Rust
Raw Normal View History

2025-04-11 12:29:29 +01:00
use main::ap::http::HttpClient;
2025-04-12 15:16:40 +01:00
use rocket::{State, get, response::status};
2025-04-11 12:29:29 +01:00
use rocket_db_pools::Connection;
use uuid::Uuid;
2025-04-12 15:16:40 +01:00
use crate::{
Db,
types::{self, activity, content, webfinger},
};
2025-04-11 12:29:29 +01:00
#[get("/finger/<account>")]
pub async fn finger_account(mut db: Connection<Db>, account: &str) -> status::Accepted<String> {
// user@host.com
let (name, host) = account.split_once("@").unwrap();
let user = resolve_user(name, host).await;
// Make actor
sqlx::query!(
r#"
INSERT INTO actor (id, inbox, outbox)
VALUES (?1, ?2, ?3)
ON CONFLICT(id) DO NOTHING
"#,
user.id,
user.inbox,
user.outbox
)
.execute(&mut **db)
.await
.unwrap();
let uuid = Uuid::new_v4().to_string();
let username = format!("{}@{}", user.name, host);
sqlx::query!(
r#"
INSERT INTO user (id, username, actor_id, display_name)
VALUES (?1, ?2, ?3, ?4)
ON CONFLICT(actor_id) DO NOTHING
2025-04-11 12:29:29 +01:00
"#,
uuid,
username,
user.id,
user.preferred_username
)
.execute(&mut **db)
.await
.unwrap();
status::Accepted(format!("https://ferri.amy.mov/users/{}", uuid))
2025-04-11 12:29:29 +01:00
}
pub async fn resolve_user(acct: &str, host: &str) -> types::Person {
let client = reqwest::Client::new();
let url = format!(
"https://{}/.well-known/webfinger?resource=acct:{}",
host, acct
);
let wf = client
.get(url)
.send()
.await
.unwrap()
.json::<webfinger::WebfingerResponse>()
.await
.unwrap();
let actor_link = wf
.links
.iter()
.find(|l| l.ty == Some("application/activity+json".to_string()))
.unwrap();
let href = actor_link.href.as_ref().unwrap();
client
.get(href)
.header("Accept", "application/activity+json")
.send()
.await
.unwrap()
.json::<types::Person>()
.await
.unwrap()
}
#[get("/test")]
pub async fn test(http: &State<HttpClient>) -> &'static str {
let user = resolve_user("amy@fedi.amy.mov", "fedi.amy.mov").await;
let post = activity::CreateActivity {
id: "https://ferri.amy.mov/activities/amy/20".to_string(),
ty: "Create".to_string(),
actor: "https://ferri.amy.mov/users/amy".to_string(),
object: content::Post {
context: "https://www.w3.org/ns/activitystreams".to_string(),
id: "https://ferri.amy.mov/users/amy/posts/20".to_string(),
ty: "Note".to_string(),
content: "My first post".to_string(),
ts: "2025-04-10T10:48:11Z".to_string(),
to: vec!["https://ferri.amy.mov/users/amy/followers".to_string()],
cc: vec!["https://www.w3.org/ns/activitystreams#Public".to_string()],
2025-04-26 12:17:32 +01:00
attributed_to: None
2025-04-11 12:29:29 +01:00
},
ts: "2025-04-10T10:48:11Z".to_string(),
to: vec!["https://ferri.amy.mov/users/amy/followers".to_string()],
cc: vec![],
};
let key_id = "https://ferri.amy.mov/users/amy#main-key";
let follow = http
.post(user.inbox)
.json(&post)
.sign(key_id)
.activity()
.send()
2025-04-12 15:16:40 +01:00
.await
.unwrap()
2025-04-11 12:29:29 +01:00
.text()
2025-04-12 15:16:40 +01:00
.await
.unwrap();
2025-04-11 12:29:29 +01:00
"Hello, world!"
2025-04-12 15:16:40 +01:00
}