chore: tidy up ID usage; fmt

This commit is contained in:
nullishamy 2025-04-12 15:16:40 +01:00
parent 244cb8b7e6
commit 2b62948447
Signed by: amy
SSH key fingerprint: SHA256:WmV0uk6WgAQvDJlM8Ld4mFPHZo02CLXXP5VkwQ5xtyk
27 changed files with 603 additions and 483 deletions

View file

@ -11,4 +11,4 @@ pub async fn new_app(app: Form<App>) -> Json<CredentialApplication> {
client_id: format!("id-for-{}", app.client_name),
client_secret: format!("secret-for-{}", app.client_name),
})
}
}

View file

@ -1,6 +1,9 @@
use rocket::{get, serde::json::Json};
use crate::types::instance::{Accounts, Configuration, Contact, Instance, MediaAttachments, Polls, Registrations, Statuses, Thumbnail, Translation, Urls};
use crate::types::instance::{
Accounts, Configuration, Contact, Instance, MediaAttachments, Polls, Registrations, Statuses,
Thumbnail, Translation, Urls,
};
#[get("/instance")]
pub async fn instance() -> Json<Instance> {
@ -59,4 +62,4 @@ pub async fn instance() -> Json<Instance> {
email: "no".to_string(),
},
})
}
}

View file

@ -1,6 +1,6 @@
pub mod user;
pub mod apps;
pub mod instance;
pub mod status;
pub mod preferences;
pub mod timeline;
pub mod status;
pub mod timeline;
pub mod user;

View file

@ -1,5 +1,7 @@
use rocket::{get, serde::{json::Json, Deserialize, Serialize}};
use rocket::{
get,
serde::{Deserialize, Serialize, json::Json},
};
#[derive(Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
@ -25,4 +27,4 @@ pub async fn preferences() -> Json<Preferences> {
reading_expand_media: "default".to_string(),
reading_expand_spoilers: false,
})
}
}

View file

@ -1,3 +1,4 @@
use crate::timeline::TimelineStatus;
use chrono::Local;
use main::ap::{self, http::HttpClient};
use rocket::{
@ -8,10 +9,9 @@ use rocket::{
};
use rocket_db_pools::Connection;
use uuid::Uuid;
use crate::timeline::TimelineStatus;
use crate::{AuthenticatedUser, Db, types::content};
use crate::api::user::CredentialAcount;
use crate::{AuthenticatedUser, Db, types::content};
#[derive(Serialize, Deserialize, Debug, FromForm)]
#[serde(crate = "rocket::serde")]
@ -19,130 +19,23 @@ pub struct Status {
status: String,
}
#[post("/statuses", data = "<status>")]
pub async fn new_status(
mut db: Connection<Db>,
http: &State<HttpClient>,
status: Form<Status>,
async fn create_status(
user: AuthenticatedUser,
) {
let user = ap::User::from_actor_id(&user.actor_id, &mut **db).await;
let outbox = ap::Outbox::for_user(user.clone(), http);
let post_id = Uuid::new_v4().to_string();
let uri = format!(
"https://ferri.amy.mov/users/{}/posts/{}",
user.username(),
post_id
);
let id = user.id();
let now = Local::now().to_rfc3339();
let post = sqlx::query!(
r#"
INSERT INTO post (id, uri, user_id, content, created_at)
VALUES (?1, ?2, ?3, ?4, ?5)
RETURNING *
"#,
post_id,
uri,
id,
status.status,
now
)
.fetch_one(&mut **db)
.await
.unwrap();
let actors = sqlx::query!("SELECT * FROM actor")
.fetch_all(&mut **db)
.await
.unwrap();
for record in actors {
// Don't send to ourselves
if &record.id == user.actor_id() {
continue
}
let create_id = format!("https://ferri.amy.mov/activities/{}", Uuid::new_v4());
let activity = ap::Activity {
id: create_id,
ty: ap::ActivityType::Create,
object: content::Post {
context: "https://www.w3.org/ns/activitystreams".to_string(),
id: uri.clone(),
content: status.status.clone(),
ty: "Note".to_string(),
ts: Local::now().to_rfc3339(),
to: vec![format!(
"https://ferri.amy.mov/users/{}/followers",
user.username()
)],
cc: vec!["https://www.w3.org/ns/activitystreams#Public".to_string()],
},
to: vec![format!(
"https://ferri.amy.mov/users/{}/followers",
user.username()
)],
cc: vec!["https://www.w3.org/ns/activitystreams#Public".to_string()],
..Default::default()
};
let actor = ap::Actor::from_raw(
record.id.clone(),
record.inbox.clone(),
record.outbox.clone(),
);
let req = ap::OutgoingActivity {
req: activity,
signed_by: format!("https://ferri.amy.mov/users/{}#main-key", user.username()),
to: actor,
};
req.save(&mut **db).await;
outbox.post(req).await;
}
}
#[post("/statuses", data = "<status>", rank = 2)]
pub async fn new_status_json(
mut db: Connection<Db>,
http: &State<HttpClient>,
status: Json<Status>,
user: AuthenticatedUser,
) -> Json<TimelineStatus> {
dbg!(&user);
http: &HttpClient,
status: &Status,
) -> TimelineStatus {
let user = ap::User::from_id(&user.username, &mut **db).await;
let outbox = ap::Outbox::for_user(user.clone(), http);
let post_id = Uuid::new_v4().to_string();
let post_id = ap::new_id();
let now = ap::new_ts();
let uri = format!(
"https://ferri.amy.mov/users/{}/posts/{}",
user.id(),
post_id
);
let id = user.id();
let now = Local::now().to_rfc3339();
let post = ap::Post::from_parts(post_id, status.status.clone(), user.clone())
.to(format!("{}/followers", user.uri()))
.cc("https://www.w3.org/ns/activitystreams#Public".to_string());
let post = sqlx::query!(
r#"
INSERT INTO post (id, uri, user_id, content, created_at)
VALUES (?1, ?2, ?3, ?4, ?5)
RETURNING *
"#,
post_id,
uri,
id,
status.status,
now
)
.fetch_one(&mut **db)
.await
.unwrap();
post.save(&mut **db).await;
let actors = sqlx::query!("SELECT * FROM actor")
.fetch_all(&mut **db)
@ -151,8 +44,8 @@ pub async fn new_status_json(
for record in actors {
// Don't send to ourselves
if &record.id == user.actor_id() {
continue
if record.id == user.actor_id() {
continue;
}
let create_id = format!("https://ferri.amy.mov/activities/{}", Uuid::new_v4());
@ -160,22 +53,8 @@ pub async fn new_status_json(
let activity = ap::Activity {
id: create_id,
ty: ap::ActivityType::Create,
object: content::Post {
context: "https://www.w3.org/ns/activitystreams".to_string(),
id: uri.clone(),
content: status.status.clone(),
ty: "Note".to_string(),
ts: Local::now().to_rfc3339(),
to: vec![format!(
"https://ferri.amy.mov/users/{}/followers",
user.username()
)],
cc: vec!["https://www.w3.org/ns/activitystreams#Public".to_string()],
},
to: vec![format!(
"https://ferri.amy.mov/users/{}/followers",
user.username()
)],
object: post.clone().to_ap(),
to: vec![format!("{}/followers", user.uri())],
cc: vec!["https://www.w3.org/ns/activitystreams#Public".to_string()],
..Default::default()
};
@ -185,9 +64,10 @@ pub async fn new_status_json(
record.inbox.clone(),
record.outbox.clone(),
);
let req = ap::OutgoingActivity {
req: activity,
signed_by: format!("https://ferri.amy.mov/users/{}#main-key", user.username()),
signed_by: format!("{}#main-key", user.uri()),
to: actor,
};
@ -195,21 +75,17 @@ pub async fn new_status_json(
outbox.post(req).await;
}
let user_uri = format!(
"https://ferri.amy.mov/users/{}",
user.id(),
);
Json(TimelineStatus {
id: post.id.clone(),
created_at: post.created_at.clone(),
TimelineStatus {
id: post.id().to_string(),
created_at: post.created_at(),
in_reply_to_id: None,
in_reply_to_account_id: None,
content: post.content.clone(),
content: post.content().to_string(),
visibility: "public".to_string(),
spoiler_text: "".to_string(),
sensitive: false,
uri: post.uri.clone(),
url: post.uri.clone(),
uri: post.uri(),
url: post.uri(),
replies_count: 0,
reblogs_count: 0,
favourites_count: 0,
@ -228,7 +104,7 @@ pub async fn new_status_json(
created_at: "2025-04-10T22:12:09Z".to_string(),
attribution_domains: vec![],
note: "".to_string(),
url: user_uri,
url: user.uri(),
avatar: "https://ferri.amy.mov/assets/pfp.png".to_string(),
avatar_static: "https://ferri.amy.mov/assets/pfp.png".to_string(),
header: "https://ferri.amy.mov/assets/pfp.png".to_string(),
@ -237,6 +113,26 @@ pub async fn new_status_json(
following_count: 1,
statuses_count: 1,
last_status_at: "2025-04-10T22:14:34Z".to_string(),
}
})
},
}
}
#[post("/statuses", data = "<status>")]
pub async fn new_status(
db: Connection<Db>,
http: &State<HttpClient>,
status: Form<Status>,
user: AuthenticatedUser,
) -> Json<TimelineStatus> {
Json(create_status(user, db, http.inner(), &status).await)
}
#[post("/statuses", data = "<status>", rank = 2)]
pub async fn new_status_json(
db: Connection<Db>,
http: &State<HttpClient>,
status: Json<Status>,
user: AuthenticatedUser,
) -> Json<TimelineStatus> {
Json(create_status(user, db, http.inner(), &status).await)
}

View file

@ -35,10 +35,11 @@ pub struct TimelineStatus {
pub async fn home(mut db: Connection<Db>, limit: i64) -> Json<Vec<TimelineStatus>> {
let posts = sqlx::query!(
r#"
SELECT p.id as "post_id", u.id as "user_id", p.content, p.uri as "post_uri", u.username, u.display_name, u.actor_id, p.created_at
FROM post p
INNER JOIN user u on p.user_id = u.id
"#
SELECT p.id as "post_id", u.id as "user_id", p.content, p.uri as "post_uri",
u.username, u.display_name, u.actor_id, p.created_at
FROM post p
INNER JOIN user u on p.user_id = u.id
"#
)
.fetch_all(&mut **db)
.await

View file

@ -6,8 +6,8 @@ use rocket::{
use rocket_db_pools::Connection;
use uuid::Uuid;
use crate::timeline::{TimelineAccount, TimelineStatus};
use crate::{AuthenticatedUser, Db, http::HttpClient};
use crate::timeline::{TimelineStatus, TimelineAccount};
#[derive(Debug, Serialize, Deserialize)]
#[serde(crate = "rocket::serde")]
@ -35,7 +35,7 @@ pub struct CredentialAcount {
#[get("/accounts/verify_credentials")]
pub async fn verify_credentials() -> Json<CredentialAcount> {
Json(CredentialAcount {
id: "https://ferri.amy.mov/users/amy".to_string(),
id: "9b9d497b-2731-435f-a929-e609ca69dac9".to_string(),
username: "amy".to_string(),
acct: "amy@ferri.amy.mov".to_string(),
display_name: "amy".to_string(),
@ -89,7 +89,11 @@ pub async fn new_follow(
}
#[get("/accounts/<uuid>")]
pub async fn account(mut db: Connection<Db>, uuid: &str, user: AuthenticatedUser) -> Json<TimelineAccount> {
pub async fn account(
mut db: Connection<Db>,
uuid: &str,
user: AuthenticatedUser,
) -> Json<TimelineAccount> {
let user = ap::User::from_id(uuid, &mut **db).await;
let user_uri = format!("https://ferri.amy.mov/users/{}", user.username());
Json(CredentialAcount {