Allow value of "attachment" property to be an object

This commit is contained in:
silverpill 2022-04-13 22:30:41 +00:00
parent 56d1ebf9e5
commit 0bc3c32fcd
2 changed files with 35 additions and 9 deletions

View file

@ -59,7 +59,7 @@ pub struct Object {
pub actor: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attachment: Option<Vec<Attachment>>,
pub attachment: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub cc: Option<Value>,

View file

@ -2,6 +2,7 @@ use std::collections::HashMap;
use actix_web::HttpRequest;
use regex::Regex;
use serde::de::DeserializeOwned;
use serde_json::Value;
use tokio_postgres::GenericClient;
use uuid::Uuid;
@ -39,7 +40,12 @@ use crate::models::relationships::queries::{
};
use crate::models::users::queries::get_user_by_name;
use crate::utils::html::clean_html;
use super::activity::{Object, Activity, create_activity_accept_follow};
use super::activity::{
Activity,
Attachment,
Object,
create_activity_accept_follow,
};
use super::actor::Actor;
use super::deliverer::deliver_activity;
use super::fetcher::fetchers::{
@ -61,7 +67,7 @@ fn parse_actor_id(
) -> Result<String, ValidationError> {
let url_regexp_str = format!(
"^{}/users/(?P<username>[0-9a-z_]+)$",
instance_url.replace(".", r"\."),
instance_url.replace('.', r"\."),
);
let url_regexp = Regex::new(&url_regexp_str)
.map_err(|_| ValidationError("error"))?;
@ -80,7 +86,7 @@ fn parse_object_id(
) -> Result<Uuid, ValidationError> {
let url_regexp_str = format!(
"^{}/objects/(?P<uuid>[0-9a-f-]+)$",
instance_url.replace(".", r"\."),
instance_url.replace('.', r"\."),
);
let url_regexp = Regex::new(&url_regexp_str)
.map_err(|_| ValidationError("error"))?;
@ -93,6 +99,7 @@ fn parse_object_id(
Ok(internal_object_id)
}
/// Transforms arbitrary property value into array of strings
fn parse_array(value: &Value) -> Result<Vec<String>, ConversionError> {
let result = match value {
Value::String(string) => vec![string.to_string()],
@ -121,6 +128,23 @@ fn parse_array(value: &Value) -> Result<Vec<String>, ConversionError> {
Ok(result)
}
/// Transforms arbitrary property value into array of structs
fn parse_property_value<T: DeserializeOwned>(value: &Value) -> Result<Vec<T>, ConversionError> {
let objects = match value {
Value::Array(array) => array.to_vec(),
Value::Object(_) => vec![value.clone()],
// Unexpected value type
_ => return Err(ConversionError),
};
let mut items = vec![];
for object in objects {
let item: T = serde_json::from_value(object)
.map_err(|_| ConversionError)?;
items.push(item);
};
Ok(items)
}
/// Parses object json value and returns its ID as string
fn get_object_id(object: Value) -> Result<String, ValidationError> {
let object_id = match object.as_str() {
@ -239,7 +263,9 @@ pub async fn import_post(
.ok_or(ValidationError("no content"))?;
let content_cleaned = clean_note_content(&content)?;
let mut attachments: Vec<Uuid> = Vec::new();
if let Some(list) = object.attachment {
if let Some(value) = object.attachment {
let list: Vec<Attachment> = parse_property_value(&value)
.map_err(|_| ValidationError("invalid attachment property"))?;
let mut downloaded = vec![];
let output_dir = config.media_dir();
for attachment in list {
@ -261,7 +287,7 @@ pub async fn import_post(
file_name,
attachment.media_type.or(media_type),
));
}
};
for (file_name, media_type) in downloaded {
let db_attachment = create_attachment(
db_client,
@ -270,8 +296,8 @@ pub async fn import_post(
media_type,
).await?;
attachments.push(db_attachment.id);
}
}
};
};
let mut mentions: Vec<Uuid> = Vec::new();
let mut tags = vec![];
if let Some(list) = object.tag {
@ -336,7 +362,7 @@ pub async fn import_post(
continue;
},
Err(other_error) => {
return Err(other_error.into());
return Err(other_error);
},
}
},