mirror of
https://github.com/nullishamy/ferri.git
synced 2025-06-28 17:14:18 +00:00
feat: attachments; other cleanup
This commit is contained in:
parent
f0e287c78d
commit
8cf7834cfe
10 changed files with 687 additions and 15 deletions
|
@ -75,6 +75,10 @@ impl<'a> HttpWrapper<'a> {
|
|||
self.get("Person", url).await
|
||||
}
|
||||
|
||||
pub async fn get_note(&self, url: &str) -> Result<ap::Post, HttpError> {
|
||||
self.get("Note", url).await
|
||||
}
|
||||
|
||||
pub async fn post_activity<T : Serialize + Debug>(
|
||||
&self,
|
||||
inbox: &str,
|
||||
|
|
|
@ -6,7 +6,7 @@ use super::outbox::OutboxRequest;
|
|||
use super::QueueMessage;
|
||||
|
||||
use chrono::DateTime;
|
||||
use tracing::warn;
|
||||
use tracing::{warn, error, Level, event};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum InboxRequest {
|
||||
|
@ -19,7 +19,7 @@ pub enum InboxRequest {
|
|||
},
|
||||
Create(ap::CreateActivity, db::User, sqlx::SqliteConnection),
|
||||
Like(ap::LikeActivity, db::User),
|
||||
Boost(ap::BoostActivity, db::User)
|
||||
Boost(ap::BoostActivity, db::User, sqlx::SqliteConnection)
|
||||
}
|
||||
|
||||
fn key_id(user: &db::User) -> String {
|
||||
|
@ -123,6 +123,7 @@ pub async fn handle_inbox_request(
|
|||
user,
|
||||
content: post.content,
|
||||
created_at,
|
||||
attachments: vec![],
|
||||
boosted_post: None
|
||||
};
|
||||
|
||||
|
@ -134,8 +135,165 @@ pub async fn handle_inbox_request(
|
|||
InboxRequest::Like(_, _) => {
|
||||
warn!("unimplemented Like in inbox");
|
||||
},
|
||||
InboxRequest::Boost(_, _) => {
|
||||
warn!("unimplemented Boost in inbox");
|
||||
InboxRequest::Boost(activity, target, mut conn) => {
|
||||
let id = key_id(&target);
|
||||
let http = HttpWrapper::new(http, &id);
|
||||
let person = http.get_person(&activity.actor).await.unwrap();
|
||||
let rmt = person.remote_info();
|
||||
|
||||
let boosted_note = http.get_note(&activity.object).await.unwrap();
|
||||
let boosted_author = if let Some(attributed_to) = &boosted_note.attributed_to {
|
||||
http.get_person(attributed_to).await.map_err(|e| {
|
||||
error!("failed to fetch attributed_to {}: {}",
|
||||
attributed_to,
|
||||
e.to_string()
|
||||
);
|
||||
()
|
||||
})
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
}.unwrap();
|
||||
|
||||
let boosted_rmt = boosted_author.remote_info();
|
||||
|
||||
event!(Level::INFO,
|
||||
boosted_by = rmt.acct,
|
||||
op = boosted_rmt.acct,
|
||||
"recording boost"
|
||||
);
|
||||
|
||||
let boosted_post = {
|
||||
let actor_uri = boosted_author.obj.id;
|
||||
let actor = db::Actor {
|
||||
id: actor_uri,
|
||||
inbox: boosted_author.inbox,
|
||||
outbox: boosted_author.outbox
|
||||
};
|
||||
|
||||
make::new_actor(actor.clone(), &mut conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let user = get::user_by_actor_uri(actor.id.clone(), &mut conn)
|
||||
.await
|
||||
.unwrap_or_else(|_| {
|
||||
db::User {
|
||||
id: ObjectUuid(crate::new_id()),
|
||||
actor,
|
||||
username: boosted_author.preferred_username,
|
||||
display_name: boosted_author.name,
|
||||
acct: boosted_rmt.acct,
|
||||
remote: boosted_rmt.is_remote,
|
||||
url: boosted_rmt.web_url,
|
||||
// FIXME: Come from boosted_author
|
||||
created_at: crate::ap::now(),
|
||||
icon_url: boosted_author.icon.map(|ic| ic.url)
|
||||
.unwrap_or("https//ferri.amy.mov/assets/pfp.png".to_string()),
|
||||
posts: db::UserPosts {
|
||||
last_post_at: None
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
make::new_user(user.clone(), &mut conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let id = crate::new_id();
|
||||
let created_at = DateTime::parse_from_rfc3339(&boosted_note.ts)
|
||||
.map(|dt| dt.to_utc())
|
||||
.unwrap();
|
||||
|
||||
let attachments = boosted_note.attachment
|
||||
.into_iter()
|
||||
.map(|at| {
|
||||
db::Attachment {
|
||||
id: ObjectUuid(crate::new_id()),
|
||||
post_id: ObjectUuid(id.clone()),
|
||||
url: at.url,
|
||||
media_type: Some(at.media_type),
|
||||
sensitive: at.sensitive,
|
||||
alt: at.summary
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
db::Post {
|
||||
id: ObjectUuid(id),
|
||||
uri: boosted_note.obj.id,
|
||||
user,
|
||||
attachments,
|
||||
content: boosted_note.content,
|
||||
created_at,
|
||||
boosted_post: None
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
make::new_post(boosted_post.clone(), &mut conn).await.unwrap();
|
||||
|
||||
let base_note = {
|
||||
let actor_uri = person.obj.id.clone();
|
||||
let actor = db::Actor {
|
||||
id: actor_uri,
|
||||
inbox: person.inbox,
|
||||
outbox: person.outbox
|
||||
};
|
||||
|
||||
make::new_actor(actor.clone(), &mut conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let user = get::user_by_actor_uri(actor.id.clone(), &mut conn)
|
||||
.await
|
||||
.unwrap_or_else(|_| {
|
||||
db::User {
|
||||
id: ObjectUuid(crate::new_id()),
|
||||
actor,
|
||||
username: person.preferred_username,
|
||||
display_name: person.name,
|
||||
acct: rmt.acct,
|
||||
remote: rmt.is_remote,
|
||||
url: rmt.web_url,
|
||||
created_at: crate::ap::now(),
|
||||
icon_url: person.icon.map(|ic| ic.url)
|
||||
.unwrap_or("https//ferri.amy.mov/assets/pfp.png".to_string()),
|
||||
posts: db::UserPosts {
|
||||
last_post_at: None
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
make::new_user(user.clone(), &mut conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let id = crate::new_id();
|
||||
let created_at = DateTime::parse_from_rfc3339(&activity.published)
|
||||
.map(|dt| dt.to_utc())
|
||||
.unwrap();
|
||||
|
||||
db::Post {
|
||||
id: ObjectUuid(id.clone()),
|
||||
uri: ObjectUri(
|
||||
format!("https://ferri.amy.mov/users/{}/posts/{}",
|
||||
person.obj.id.0,
|
||||
id
|
||||
)
|
||||
),
|
||||
user,
|
||||
attachments: vec![],
|
||||
content: String::new(),
|
||||
created_at,
|
||||
boosted_post: Some(boosted_post.id.clone())
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
make::new_post(base_note, &mut conn).await.unwrap();
|
||||
},
|
||||
}
|
||||
}
|
||||
|
|
|
@ -207,8 +207,29 @@ pub async fn posts_for_user_id(
|
|||
.fetch_all(&mut *conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
for record in posts {
|
||||
let attachments = sqlx::query!(
|
||||
"SELECT * FROM attachment WHERE post_id = ?",
|
||||
record.post_id
|
||||
)
|
||||
.fetch_all(&mut *conn)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let attachments = attachments.into_iter()
|
||||
.map(|at| {
|
||||
db::Attachment {
|
||||
id: ObjectUuid(at.id),
|
||||
post_id: ObjectUuid(at.post_id),
|
||||
url: at.url,
|
||||
media_type: Some(at.media_type),
|
||||
sensitive: at.marked_sensitive,
|
||||
alt: at.alt
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let user_created = parse_ts(record.user_created)
|
||||
.expect("no db corruption");
|
||||
|
||||
|
@ -233,6 +254,7 @@ pub async fn posts_for_user_id(
|
|||
last_post_at: None
|
||||
}
|
||||
},
|
||||
attachments,
|
||||
content: record.content,
|
||||
created_at: parse_ts(record.post_created).unwrap(),
|
||||
boosted_post: None
|
||||
|
|
|
@ -68,6 +68,28 @@ pub async fn new_follow(
|
|||
Ok(follow)
|
||||
}
|
||||
|
||||
pub async fn new_attachment(
|
||||
attachment: db::Attachment,
|
||||
conn: &mut SqliteConnection
|
||||
) -> Result<db::Attachment, DbError> {
|
||||
sqlx::query!(
|
||||
r#"
|
||||
INSERT INTO attachment (id, post_id, url, media_type, marked_sensitive, alt)
|
||||
VALUES (?1, ?2, ?3, ?4, ?5, ?6)
|
||||
"#,
|
||||
attachment.id.0,
|
||||
attachment.post_id.0,
|
||||
attachment.url,
|
||||
attachment.media_type,
|
||||
attachment.sensitive,
|
||||
attachment.alt
|
||||
)
|
||||
.execute(conn)
|
||||
.await
|
||||
.map_err(|e| DbError::CreationError(e.to_string()))?;
|
||||
|
||||
Ok(attachment)
|
||||
}
|
||||
|
||||
pub async fn new_post(
|
||||
post: db::Post,
|
||||
|
@ -88,11 +110,14 @@ pub async fn new_post(
|
|||
post.content,
|
||||
ts,
|
||||
boosted
|
||||
|
||||
)
|
||||
.execute(conn)
|
||||
.await
|
||||
.map_err(|e| DbError::CreationError(e.to_string()))?;
|
||||
.execute(&mut *conn)
|
||||
.await
|
||||
.map_err(|e| DbError::CreationError(e.to_string()))?;
|
||||
|
||||
for attachment in post.attachments.clone() {
|
||||
new_attachment(attachment, &mut *conn).await?;
|
||||
}
|
||||
|
||||
Ok(post)
|
||||
}
|
||||
|
|
|
@ -98,6 +98,16 @@ pub mod db {
|
|||
pub posts: UserPosts,
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct Attachment {
|
||||
pub id: ObjectUuid,
|
||||
pub post_id: ObjectUuid,
|
||||
pub url: String,
|
||||
pub media_type: Option<String>,
|
||||
pub sensitive: bool,
|
||||
pub alt: Option<String>
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone)]
|
||||
pub struct Post {
|
||||
pub id: ObjectUuid,
|
||||
|
@ -105,7 +115,8 @@ pub mod db {
|
|||
pub user: User,
|
||||
pub content: String,
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub boosted_post: Option<ObjectUuid>
|
||||
pub boosted_post: Option<ObjectUuid>,
|
||||
pub attachments: Vec<Attachment>
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,6 +214,25 @@ pub mod ap {
|
|||
pub object: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub enum PostAttachmentType {
|
||||
Document
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PostAttachment {
|
||||
#[serde(rename = "type")]
|
||||
pub ty: PostAttachmentType,
|
||||
|
||||
pub media_type: String,
|
||||
pub url: String,
|
||||
pub name: String,
|
||||
pub summary: Option<String>,
|
||||
#[serde(default)]
|
||||
pub sensitive: bool
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct Post {
|
||||
#[serde(flatten)]
|
||||
|
@ -217,6 +247,8 @@ pub mod ap {
|
|||
pub to: Vec<String>,
|
||||
pub cc: Vec<String>,
|
||||
|
||||
pub attachment: Vec<PostAttachment>,
|
||||
|
||||
#[serde(rename = "attributedTo")]
|
||||
pub attributed_to: Option<String>,
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue