fix(apb): actually link href is not guaranteed
This commit is contained in:
parent
c3e319d5a9
commit
2b4fb3bd62
7 changed files with 42 additions and 35 deletions
|
@ -102,7 +102,7 @@ impl<T : super::Base> Node<T> {
|
|||
pub fn id(&self) -> crate::Field<&str> {
|
||||
match self {
|
||||
Node::Empty => Err(crate::FieldErr("id")),
|
||||
Node::Link(uri) => Ok(uri.href()),
|
||||
Node::Link(uri) => uri.href(),
|
||||
Node::Object(obj) => obj.id(),
|
||||
Node::Array(arr) => arr.front().map(|x| x.id()).ok_or(crate::FieldErr("id"))?,
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ impl<T : super::Base> Node<T> {
|
|||
pub fn all_ids(&self) -> Vec<String> {
|
||||
match self {
|
||||
Node::Empty => vec![],
|
||||
Node::Link(uri) => vec![uri.href().to_string()],
|
||||
Node::Link(uri) => uri.href().map(|x| vec![x.to_string()]).unwrap_or_default(),
|
||||
Node::Object(x) => x.id().map_or(vec![], |x| vec![x.to_string()]),
|
||||
Node::Array(x) => x.iter().filter_map(|x| Some(x.id().ok()?.to_string())).collect()
|
||||
}
|
||||
|
@ -236,7 +236,7 @@ impl From<Node<serde_json::Value>> for serde_json::Value {
|
|||
fn from(value: Node<serde_json::Value>) -> Self {
|
||||
match value {
|
||||
Node::Empty => serde_json::Value::Null,
|
||||
Node::Link(l) => serde_json::Value::String(l.href().to_string()), // TODO there could be more
|
||||
Node::Link(l) => serde_json::Value::String(l.href().unwrap_or_default().to_string()), // TODO there could be more
|
||||
Node::Object(o) => *o,
|
||||
Node::Array(arr) =>
|
||||
serde_json::Value::Array(arr.into_iter().map(|x| x.into()).collect()),
|
||||
|
|
|
@ -19,7 +19,7 @@ crate::strenum! {
|
|||
|
||||
pub trait Link : crate::Base {
|
||||
fn link_type(&self) -> Field<LinkType> { Err(FieldErr("type")) }
|
||||
fn href(&self) -> &str;
|
||||
fn href(&self) -> Field<&str>;
|
||||
fn rel(&self) -> Field<&str> { Err(FieldErr("rel")) }
|
||||
fn media_type(&self) -> Field<&str> { Err(FieldErr("mediaType")) } // also in obj
|
||||
fn name(&self) -> Field<&str> { Err(FieldErr("name")) } // also in obj
|
||||
|
@ -31,7 +31,7 @@ pub trait Link : crate::Base {
|
|||
|
||||
pub trait LinkMut : crate::BaseMut {
|
||||
fn set_link_type(self, val: Option<LinkType>) -> Self;
|
||||
fn set_href(self, href: &str) -> Self;
|
||||
fn set_href(self, href: Option<&str>) -> Self;
|
||||
fn set_rel(self, val: Option<&str>) -> Self;
|
||||
fn set_media_type(self, val: Option<&str>) -> Self; // also in obj
|
||||
fn set_name(self, val: Option<&str>) -> Self; // also in obj
|
||||
|
@ -42,19 +42,19 @@ pub trait LinkMut : crate::BaseMut {
|
|||
}
|
||||
|
||||
impl Link for String {
|
||||
fn href(&self) -> &str {
|
||||
self
|
||||
fn href(&self) -> Field<&str> {
|
||||
Ok(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstructured")]
|
||||
impl Link for serde_json::Value {
|
||||
// TODO this can fail, but it should never do!
|
||||
fn href(&self) -> &str {
|
||||
fn href(&self) -> Field<&str> {
|
||||
if self.is_string() {
|
||||
self.as_str().unwrap_or("")
|
||||
self.as_str().ok_or(FieldErr("href"))
|
||||
} else {
|
||||
self.get("href").map(|x| x.as_str().unwrap_or("")).unwrap_or("")
|
||||
self.get("href").and_then(|x| x.as_str()).ok_or(FieldErr("href"))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -70,15 +70,18 @@ impl Link for serde_json::Value {
|
|||
|
||||
#[cfg(feature = "unstructured")]
|
||||
impl LinkMut for serde_json::Value {
|
||||
fn set_href(mut self, href: &str) -> Self {
|
||||
fn set_href(mut self, href: Option<&str>) -> Self {
|
||||
match &mut self {
|
||||
serde_json::Value::Object(map) => {
|
||||
map.insert(
|
||||
"href".to_string(),
|
||||
serde_json::Value::String(href.to_string())
|
||||
);
|
||||
match href {
|
||||
Some(href) => map.insert(
|
||||
"href".to_string(),
|
||||
serde_json::Value::String(href.to_string())
|
||||
),
|
||||
None => map.remove("href"),
|
||||
};
|
||||
},
|
||||
x => *x = serde_json::Value::String(href.to_string()),
|
||||
x => *x = serde_json::Value::String(href.unwrap_or_default().to_string()),
|
||||
}
|
||||
self
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ impl<T: apb::Base> From<apb::Node<T>> for Audience {
|
|||
Audience(
|
||||
match value {
|
||||
apb::Node::Empty => vec![],
|
||||
apb::Node::Link(l) => vec![l.href().to_string()],
|
||||
apb::Node::Link(l) => l.href().map(|x| vec![x.to_string()]).unwrap_or_default(),
|
||||
apb::Node::Object(o) => if let Ok(id) = o.id() { vec![id.to_string()] } else { vec![] },
|
||||
apb::Node::Array(arr) => arr.into_iter().filter_map(|l| l.id().str()).collect(),
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ impl RichMention {
|
|||
use apb::LinkMut;
|
||||
apb::new()
|
||||
.set_link_type(Some(apb::LinkType::Mention))
|
||||
.set_href(&self.id)
|
||||
.set_href(Some(&self.id))
|
||||
.set_name(Some(&self.fqn))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -427,11 +427,13 @@ pub trait Fetchable : Sync + Send {
|
|||
impl Fetchable for apb::Node<serde_json::Value> {
|
||||
async fn fetch(&mut self, ctx: &crate::Context) -> Result<&mut Self, PullError> {
|
||||
if let apb::Node::Link(uri) = self {
|
||||
*self = crate::Context::request(Method::GET, uri.href(), None, ctx.base(), ctx.pkey(), ctx.domain())
|
||||
.await?
|
||||
.json::<serde_json::Value>()
|
||||
.await?
|
||||
.into();
|
||||
if let Ok(href) = uri.href() {
|
||||
*self = crate::Context::request(Method::GET, href, None, ctx.base(), ctx.pkey(), ctx.domain())
|
||||
.await?
|
||||
.json::<serde_json::Value>()
|
||||
.await?
|
||||
.into();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(self)
|
||||
|
|
|
@ -77,7 +77,7 @@ impl Normalizer for crate::Context {
|
|||
},
|
||||
Node::Link(l) => crate::model::attachment::ActiveModel {
|
||||
internal: sea_orm::ActiveValue::NotSet,
|
||||
url: Set(l.href().to_string()),
|
||||
url: Set(l.href().unwrap_or_default().to_string()),
|
||||
object: Set(object_model.internal),
|
||||
document_type: Set(apb::DocumentType::Page),
|
||||
name: Set(l.name().str()),
|
||||
|
@ -96,20 +96,22 @@ impl Normalizer for crate::Context {
|
|||
Node::Empty | Node::Object(_) | Node::Array(_) => {},
|
||||
Node::Link(l) => match l.link_type() {
|
||||
Ok(apb::LinkType::Mention) => {
|
||||
if let Some(internal) = crate::model::actor::Entity::ap_to_internal(l.href(), tx).await? {
|
||||
let model = crate::model::mention::ActiveModel {
|
||||
internal: NotSet,
|
||||
object: Set(object_model.internal),
|
||||
actor: Set(internal),
|
||||
};
|
||||
crate::model::mention::Entity::insert(model)
|
||||
.exec(tx)
|
||||
.await?;
|
||||
if let Ok(href) = l.href() {
|
||||
if let Some(internal) = crate::model::actor::Entity::ap_to_internal(href, tx).await? {
|
||||
let model = crate::model::mention::ActiveModel {
|
||||
internal: NotSet,
|
||||
object: Set(object_model.internal),
|
||||
actor: Set(internal),
|
||||
};
|
||||
crate::model::mention::Entity::insert(model)
|
||||
.exec(tx)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
},
|
||||
Ok(apb::LinkType::Hashtag) => {
|
||||
let hashtag = l.name()
|
||||
.unwrap_or_else(|_| l.href().split('/').last().unwrap_or_default())
|
||||
.unwrap_or_else(|_| l.href().unwrap_or_default().split('/').last().unwrap_or_default()) // TODO maybe just fail?
|
||||
.replace('#', "");
|
||||
let model = crate::model::hashtag::ActiveModel {
|
||||
internal: NotSet,
|
||||
|
|
|
@ -72,7 +72,7 @@ pub fn Object(
|
|||
})
|
||||
},
|
||||
Ok(apb::LinkType::Mention) => {
|
||||
let uid = apb::Link::href(link.as_ref());
|
||||
let uid = apb::Link::href(link.as_ref()).unwrap_or_default();
|
||||
let mention = apb::Link::name(link.as_ref()).unwrap_or_default().replacen('@', "", 1);
|
||||
let (username, domain) = if let Some((username, server)) = mention.split_once('@') {
|
||||
(username.to_string(), server.to_string())
|
||||
|
|
Loading…
Reference in a new issue