Remove usage of Option::unwrap() in activitypub code #80

Merged
dessalines merged 2 commits from apub-remove-unwrap into main 2020-08-11 14:31:09 +00:00
22 changed files with 528 additions and 282 deletions

View File

@ -31,6 +31,18 @@ use regex::{Regex, RegexBuilder};
use std::io::{Error, ErrorKind};
use url::Url;
#[macro_export]
macro_rules! location_info {
() => {
format!(
"None value at {}:{}, column {}",
file!(),
line!(),
column!()
)
};
}
pub fn to_datetime_utc(ndt: NaiveDateTime) -> DateTime<Utc> {
DateTime::<Utc>::from_utc(ndt, Utc)
}

View File

@ -605,11 +605,11 @@ impl Perform for Oper<FollowCommunity> {
// Dont actually add to the community followers here, because you need
// to wait for the accept
user
.send_follow(&community.actor_id, &self.client, pool)
.send_follow(&community.actor_id()?, &self.client, pool)
.await?;
} else {
user
.send_unfollow(&community.actor_id, &self.client, pool)
.send_unfollow(&community.actor_id()?, &self.client, pool)
.await?;
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
if blocking(pool, unfollow).await?.is_err() {

View File

@ -21,7 +21,7 @@ use uuid::Uuid;
pub async fn send_activity_to_community(
creator: &User_,
community: &Community,
to: Vec<String>,
to: Vec<Url>,
activity: AnyBase,
client: &Client,
pool: &DbPool,
@ -43,17 +43,18 @@ pub async fn send_activity(
client: &Client,
activity: &AnyBase,
actor: &dyn ActorType,
to: Vec<String>,
to: Vec<Url>,
) -> Result<(), LemmyError> {
let activity = serde_json::to_string(&activity)?;
debug!("Sending activitypub activity {} to {:?}", activity, to);
for t in to {
let to_url = Url::parse(&t)?;
for to_url in to {
check_is_apub_id_valid(&to_url)?;
let res = retry_custom(|| async {
let request = client.post(&t).header("Content-Type", "application/json");
let request = client
.post(to_url.as_str())
.header("Content-Type", "application/json");
match sign(request, actor, activity.clone()).await {
Ok(signed) => Ok(signed.send().await),

View File

@ -41,6 +41,7 @@ use activitystreams::{
public,
};
use actix_web::{body::Body, client::Client, web::Path, HttpResponse};
use anyhow::Context;
use itertools::Itertools;
use lemmy_db::{
comment::{Comment, CommentForm},
@ -49,7 +50,13 @@ use lemmy_db::{
user::User_,
Crud,
};
use lemmy_utils::{convert_datetime, remove_slurs, scrape_text_for_mentions, MentionData};
use lemmy_utils::{
convert_datetime,
location_info,
remove_slurs,
scrape_text_for_mentions,
MentionData,
};
use log::debug;
use serde::Deserialize;
use serde_json::Error;
@ -136,21 +143,21 @@ impl FromApub for CommentForm {
) -> Result<CommentForm, LemmyError> {
let creator_actor_id = &note
.attributed_to()
.unwrap()
.context(location_info!())?
.as_single_xsd_any_uri()
.unwrap();
.context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?;
let mut in_reply_tos = note
.in_reply_to()
.as_ref()
.unwrap()
.context(location_info!())?
.as_many()
.unwrap()
.context(location_info!())?
.iter()
.map(|i| i.as_xsd_any_uri().unwrap());
let post_ap_id = in_reply_tos.next().unwrap();
.map(|i| i.as_xsd_any_uri().context(""));
let post_ap_id = in_reply_tos.next().context(location_info!())??;
// This post, or the parent comment might not yet exist on this server yet, fetch them.
let post = get_or_fetch_and_insert_post(&post_ap_id, client, pool).await?;
@ -159,7 +166,7 @@ impl FromApub for CommentForm {
// For deeply nested comments, FromApub automatically gets called recursively
let parent_id: Option<i32> = match in_reply_tos.next() {
Some(parent_comment_uri) => {
let parent_comment_ap_id = &parent_comment_uri;
let parent_comment_ap_id = &parent_comment_uri?;
let parent_comment =
get_or_fetch_and_insert_comment(&parent_comment_ap_id, client, pool).await?;
@ -169,9 +176,9 @@ impl FromApub for CommentForm {
};
let content = note
.content()
.unwrap()
.context(location_info!())?
.as_single_xsd_string()
.unwrap()
.context(location_info!())?
.to_string();
let content_slurs_removed = remove_slurs(&content);
@ -295,7 +302,7 @@ impl ApubObjectType for Comment {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
delete.into_any_base()?,
client,
pool,
@ -337,7 +344,7 @@ impl ApubObjectType for Comment {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
undo.into_any_base()?,
client,
pool,
@ -370,7 +377,7 @@ impl ApubObjectType for Comment {
send_activity_to_community(
&mod_,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
remove.into_any_base()?,
client,
pool,
@ -412,7 +419,7 @@ impl ApubObjectType for Comment {
send_activity_to_community(
&mod_,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
undo.into_any_base()?,
client,
pool,
@ -448,7 +455,7 @@ impl ApubLikeableType for Comment {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
like.into_any_base()?,
client,
pool,
@ -481,7 +488,7 @@ impl ApubLikeableType for Comment {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
dislike.into_any_base()?,
client,
pool,
@ -522,7 +529,7 @@ impl ApubLikeableType for Comment {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
undo.into_any_base()?,
client,
pool,
@ -534,7 +541,7 @@ impl ApubLikeableType for Comment {
struct MentionsAndAddresses {
addressed_ccs: Vec<String>,
inboxes: Vec<String>,
inboxes: Vec<Url>,
tags: Vec<Mention>,
}
@ -569,7 +576,7 @@ async fn collect_non_local_mentions_and_addresses(
.filter(|m| !m.is_local())
.collect::<Vec<MentionData>>();
let mut mention_inboxes = Vec::new();
let mut mention_inboxes: Vec<Url> = Vec::new();
for mention in &mentions {
// TODO should it be fetching it every time?
if let Ok(actor_id) = fetch_webfinger_url(mention, client).await {
@ -577,7 +584,7 @@ async fn collect_non_local_mentions_and_addresses(
addressed_ccs.push(actor_id.to_owned().to_string());
let mention_user = get_or_fetch_and_upsert_user(&actor_id, client, pool).await?;
let shared_inbox = mention_user.get_shared_inbox_url();
let shared_inbox = mention_user.get_shared_inbox_url()?;
mention_inboxes.push(shared_inbox);
let mut mention_tag = Mention::new();
@ -586,7 +593,7 @@ async fn collect_non_local_mentions_and_addresses(
}
}
let mut inboxes = vec![community.get_shared_inbox_url()];
let mut inboxes = vec![community.get_shared_inbox_url()?];
inboxes.extend(mention_inboxes);
inboxes = inboxes.into_iter().unique().collect();

View File

@ -7,8 +7,7 @@ use crate::{
create_apub_tombstone_response,
create_tombstone,
extensions::group_extensions::GroupExtension,
fetcher::get_or_fetch_and_upsert_user,
get_shared_inbox,
fetcher::{get_or_fetch_and_upsert_actor, get_or_fetch_and_upsert_user},
insert_activity,
ActorType,
FromApub,
@ -40,6 +39,7 @@ use activitystreams::{
};
use activitystreams_ext::Ext2;
use actix_web::{body::Body, client::Client, web, HttpResponse};
use anyhow::Context;
use itertools::Itertools;
use lemmy_db::{
community::{Community, CommunityForm},
@ -48,7 +48,7 @@ use lemmy_db::{
post::Post,
user::User_,
};
use lemmy_utils::convert_datetime;
use lemmy_utils::{convert_datetime, get_apub_protocol_string, location_info};
use serde::Deserialize;
use url::Url;
@ -99,7 +99,7 @@ impl ToApub for Community {
.set_following(self.get_following_url().parse()?)
.set_liked(self.get_liked_url().parse()?)
.set_endpoints(Endpoints {
shared_inbox: Some(self.get_shared_inbox_url().parse()?),
shared_inbox: Some(self.get_shared_inbox_url()?),
..Default::default()
});
@ -113,7 +113,7 @@ impl ToApub for Community {
Ok(Ext2::new(
ap_actor,
group_extension,
self.get_public_key_ext(),
self.get_public_key_ext()?,
))
}
@ -128,11 +128,11 @@ impl ActorType for Community {
self.actor_id.to_owned()
}
fn public_key(&self) -> String {
self.public_key.to_owned().unwrap()
fn public_key(&self) -> Option<String> {
self.public_key.to_owned()
}
fn private_key(&self) -> String {
self.private_key.to_owned().unwrap()
fn private_key(&self) -> Option<String> {
self.private_key.to_owned()
}
/// As a local community, accept the follow request from a remote user.
@ -142,10 +142,14 @@ impl ActorType for Community {
client: &Client,
pool: &DbPool,
) -> Result<(), LemmyError> {
let actor_uri = follow.actor()?.as_single_xsd_any_uri().unwrap().to_string();
let actor_uri = follow
.actor()?
.as_single_xsd_any_uri()
.context(location_info!())?;
let actor = get_or_fetch_and_upsert_actor(actor_uri, client, pool).await?;
let mut accept = Accept::new(self.actor_id.to_owned(), follow.into_any_base()?);
let to = format!("{}/inbox", actor_uri);
let to = actor.get_inbox_url()?;
accept
.set_context(context())
.set_id(generate_activity_id(AcceptType::Accept)?)
@ -279,7 +283,10 @@ impl ActorType for Community {
}
/// For a given community, returns the inboxes of all followers.
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<String>, LemmyError> {
///
/// TODO: this function is very badly implemented, we should just store shared_inbox_url in
/// CommunityFollowerView
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
let id = self.id;
let inboxes = blocking(pool, move |conn| {
@ -288,8 +295,22 @@ impl ActorType for Community {
.await??;
let inboxes = inboxes
.into_iter()
.map(|c| get_shared_inbox(&Url::parse(&c.user_actor_id).unwrap()))
.filter(|s| !s.is_empty())
.map(|u| -> Result<Url, LemmyError> {
let url = Url::parse(&u.user_actor_id)?;
let domain = url.domain().context(location_info!())?;
let port = if let Some(port) = url.port() {
format!(":{}", port)
} else {
"".to_string()
};
Ok(Url::parse(&format!(
"{}://{}{}/inbox",
get_apub_protocol_string(),
domain,
port,
))?)
})
.filter_map(Result::ok)
.unique()
.collect();
@ -298,7 +319,7 @@ impl ActorType for Community {
async fn send_follow(
&self,
_follow_actor_id: &str,
_follow_actor_id: &Url,
_client: &Client,
_pool: &DbPool,
) -> Result<(), LemmyError> {
@ -307,7 +328,7 @@ impl ActorType for Community {
async fn send_unfollow(
&self,
_follow_actor_id: &str,
_follow_actor_id: &Url,
_client: &Client,
_pool: &DbPool,
) -> Result<(), LemmyError> {
@ -330,44 +351,50 @@ impl FromApub for CommunityForm {
pool: &DbPool,
expected_domain: Option<Url>,
) -> Result<Self, LemmyError> {
let creator_and_moderator_uris = group.inner.attributed_to().unwrap();
let creator_and_moderator_uris = group.inner.attributed_to().context(location_info!())?;
let creator_uri = creator_and_moderator_uris
.as_many()
.unwrap()
.context(location_info!())?
.iter()
.next()
.unwrap()
.context(location_info!())?
.as_xsd_any_uri()
.unwrap();
.context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_uri, client, pool).await?;
let name = group
.inner
.name()
.unwrap()
.context(location_info!())?
.as_one()
.unwrap()
.context(location_info!())?
.as_xsd_string()
.unwrap()
.context(location_info!())?
.to_string();
let title = group
.inner
.preferred_username()
.context(location_info!())?
.to_string();
let title = group.inner.preferred_username().unwrap().to_string();
// TODO: should be parsed as html and tags like <script> removed (or use markdown source)
// -> same for post.content etc
let description = group
.inner
.content()
.map(|s| s.as_single_xsd_string().unwrap().into());
.map(|s| s.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
check_slurs(&name)?;
check_slurs(&title)?;
check_slurs_opt(&description)?;
let icon = match group.icon() {
Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone())
.unwrap()
.unwrap()
Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
.context(location_info!())?
.context(location_info!())?
.url()
.unwrap()
.context(location_info!())?
.as_single_xsd_any_uri()
.map(|u| u.to_string()),
),
@ -376,11 +403,11 @@ impl FromApub for CommunityForm {
let banner = match group.image() {
Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone())
.unwrap()
.unwrap()
Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
.context(location_info!())?
.context(location_info!())?
.url()
.unwrap()
.context(location_info!())?
.as_single_xsd_any_uri()
.map(|u| u.to_string()),
),
@ -499,13 +526,15 @@ pub async fn do_announce(
insert_activity(community.creator_id, announce.clone(), true, pool).await?;
let mut to = community.get_follower_inboxes(pool).await?;
let mut to: Vec<Url> = community.get_follower_inboxes(pool).await?;
// dont send to the local instance, nor to the instance where the activity originally came from,
// because that would result in a database error (same data inserted twice)
// this seems to be the "easiest" stable alternative for remove_item()
to.retain(|x| *x != sender.get_shared_inbox_url());
to.retain(|x| *x != community.get_shared_inbox_url());
let sender_shared_inbox = sender.get_shared_inbox_url()?;
to.retain(|x| x != &sender_shared_inbox);
let community_shared_inbox = community.get_shared_inbox_url()?;
to.retain(|x| x != &community_shared_inbox);
send_activity(client, &announce.into_any_base()?, community, to).await?;

View File

@ -2,11 +2,12 @@ use crate::{apub::ActorType, LemmyError};
use activitystreams::unparsed::UnparsedMutExt;
use activitystreams_ext::UnparsedExtension;
use actix_web::{client::ClientRequest, HttpRequest};
use anyhow::anyhow;
use anyhow::{anyhow, Context};
use http_signature_normalization_actix::{
digest::{DigestClient, SignExt},
Config,
};
use lemmy_utils::location_info;
use log::debug;
use openssl::{
hash::MessageDigest,
@ -27,7 +28,7 @@ pub async fn sign(
activity: String,
) -> Result<DigestClient<String>, LemmyError> {
let signing_key_id = format!("{}#main-key", actor.actor_id()?);
let private_key = actor.private_key();
let private_key = actor.private_key().context(location_info!())?;
let digest_client = request
.signature_with_digest(
@ -37,8 +38,8 @@ pub async fn sign(
activity,
move |signing_string| {
let private_key = PKey::private_key_from_pem(private_key.as_bytes())?;
let mut signer = Signer::new(MessageDigest::sha256(), &private_key).unwrap();
signer.update(signing_string.as_bytes()).unwrap();
let mut signer = Signer::new(MessageDigest::sha256(), &private_key)?;
signer.update(signing_string.as_bytes())?;
Ok(base64::encode(signer.sign_to_vec()?)) as Result<_, LemmyError>
},
@ -49,6 +50,7 @@ pub async fn sign(
}
pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyError> {
let public_key = actor.public_key().context(location_info!())?;
let verified = HTTP_SIG_CONFIG
.begin_verify(
request.method(),
@ -58,12 +60,11 @@ pub fn verify(request: &HttpRequest, actor: &dyn ActorType) -> Result<(), LemmyE
.verify(|signature, signing_string| -> Result<bool, LemmyError> {
debug!(
"Verifying with key {}, message {}",
&actor.public_key(),
&signing_string
&public_key, &signing_string
);
let public_key = PKey::public_key_from_pem(actor.public_key().as_bytes())?;
let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key).unwrap();
verifier.update(&signing_string.as_bytes()).unwrap();
let public_key = PKey::public_key_from_pem(public_key.as_bytes())?;
let mut verifier = Verifier::new(MessageDigest::sha256(), &public_key)?;
verifier.update(&signing_string.as_bytes())?;
Ok(verifier.verify(&base64::decode(signature)?)?)
})?;

View File

@ -17,7 +17,7 @@ use crate::{
};
use activitystreams::{base::BaseExt, collection::OrderedCollection, object::Note, prelude::*};
use actix_web::client::Client;
use anyhow::anyhow;
use anyhow::{anyhow, Context};
use chrono::NaiveDateTime;
use diesel::{result::Error::NotFound, PgConnection};
use lemmy_db::{
@ -34,7 +34,7 @@ use lemmy_db::{
Joinable,
SearchType,
};
use lemmy_utils::get_apub_protocol_string;
use lemmy_utils::{get_apub_protocol_string, location_info};
use log::debug;
use serde::Deserialize;
use std::{fmt::Debug, time::Duration};
@ -144,10 +144,10 @@ pub async fn search_by_apub_id(
users: vec![],
};
let domain = query_url.domain().unwrap();
let domain = query_url.domain().context("url has no domain")?;
let response = match fetch_remote_object::<SearchAcceptedObjects>(client, &query_url).await? {
SearchAcceptedObjects::Person(p) => {
let user_uri = p.inner.id(domain)?.unwrap();
let user_uri = p.inner.id(domain)?.context("person has no id")?;
let user = get_or_fetch_and_upsert_user(&user_uri, client, pool).await?;
@ -157,7 +157,7 @@ pub async fn search_by_apub_id(
response
}
SearchAcceptedObjects::Group(g) => {
let community_uri = g.inner.id(domain)?.unwrap();
let community_uri = g.inner.id(domain)?.context("group has no id")?;
let community = get_or_fetch_and_upsert_community(community_uri, client, pool).await?;
@ -181,10 +181,19 @@ pub async fn search_by_apub_id(
response
}
SearchAcceptedObjects::Comment(c) => {
let post_url = c.in_reply_to().as_ref().unwrap().as_many().unwrap();
let post_url = c
.in_reply_to()
.as_ref()
.context(location_info!())?
.as_many()
.context(location_info!())?;
// TODO: also fetch parent comments if any
let x = post_url.first().unwrap().as_xsd_any_uri().unwrap();
let x = post_url
.first()
.context(location_info!())?
.as_xsd_any_uri()
.context(location_info!())?;
let post = fetch_remote_object(client, x).await?;
let post_form = PostForm::from_apub(&post, client, pool, Some(query_url.clone())).await?;
let comment_form = CommentForm::from_apub(&c, client, pool, Some(query_url)).await?;
@ -312,13 +321,13 @@ async fn fetch_remote_community(
.await??;
// Also add the community moderators too
let attributed_to = group.inner.attributed_to().unwrap();
let attributed_to = group.inner.attributed_to().context(location_info!())?;
let creator_and_moderator_uris: Vec<&Url> = attributed_to
.as_many()
.unwrap()
.context(location_info!())?
.iter()
.map(|a| a.as_xsd_any_uri().unwrap())
.collect();
.map(|a| a.as_xsd_any_uri().context(""))
.collect::<Result<Vec<&Url>, anyhow::Error>>()?;
let mut creator_and_moderators = Vec::new();
@ -348,9 +357,9 @@ async fn fetch_remote_community(
// fetch outbox (maybe make this conditional)
let outbox =
fetch_remote_object::<OrderedCollection>(client, &community.get_outbox_url()?).await?;
let outbox_items = outbox.items().unwrap().clone();
for o in outbox_items.many().unwrap() {
let page = PageExt::from_any_base(o)?.unwrap();
let outbox_items = outbox.items().context(location_info!())?.clone();
for o in outbox_items.many().context(location_info!())? {
let page = PageExt::from_any_base(o)?.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?;
let post_ap_id = post.ap_id.clone();
// Check whether the post already exists in the local db
@ -452,7 +461,7 @@ pub async fn get_or_fetch_and_insert_comment(
// Ok(
// items
// .unwrap()
// .context(location_info!())?
// .map(|obox: &BaseBox| -> Result<PostForm, LemmyError> {
// let page = obox.clone().to_concrete::<Page>()?;
// PostForm::from_page(&page, conn)

View File

@ -21,6 +21,8 @@ use activitystreams::{
prelude::ExtendsExt,
};
use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_utils::location_info;
pub async fn receive_announce(
activity: AnyBase,
@ -28,15 +30,15 @@ pub async fn receive_announce(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let announce = Announce::from_any_base(activity)?.unwrap();
let announce = Announce::from_any_base(activity)?.context(location_info!())?;
// ensure that announce and community come from the same instance
let community = get_community_id_from_activity(&announce)?;
announce.id(community.domain().unwrap())?;
announce.id(community.domain().context(location_info!())?)?;
let kind = announce.object().as_single_kind_str();
let object = announce.object();
let object2 = object.clone().one().unwrap();
let object2 = object.clone().one().context(location_info!())?;
match kind {
Some("Create") => receive_create(object2, client, pool, chat_server).await,
Some("Update") => receive_update(object2, client, pool, chat_server).await,

View File

@ -24,6 +24,7 @@ use crate::{
};
use activitystreams::{activity::Create, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{
comment::{Comment, CommentForm},
comment_view::CommentView,
@ -31,7 +32,7 @@ use lemmy_db::{
post_view::PostView,
Crud,
};
use lemmy_utils::scrape_text_for_mentions;
use lemmy_utils::{location_info, scrape_text_for_mentions};
pub async fn receive_create(
activity: AnyBase,
@ -39,11 +40,11 @@ pub async fn receive_create(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let create = Create::from_any_base(activity)?.unwrap();
let create = Create::from_any_base(activity)?.context(location_info!())?;
// ensure that create and actor come from the same instance
let user = get_user_from_activity(&create, client, pool).await?;
create.id(user.actor_id()?.domain().unwrap())?;
create.id(user.actor_id()?.domain().context(location_info!())?)?;
match create.object().as_single_kind_str() {
Some("Page") => receive_create_post(create, client, pool, chat_server).await,
@ -59,7 +60,8 @@ async fn receive_create_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&create, client, pool).await?;
let page = PageExt::from_any_base(create.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?;
@ -91,7 +93,8 @@ async fn receive_create_comment(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&create, client, pool).await?;
let note = Note::from_any_base(create.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(create.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)).await?;

View File

@ -23,6 +23,7 @@ use crate::{
};
use activitystreams::{activity::Delete, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{
comment::{Comment, CommentForm},
comment_view::CommentView,
@ -33,6 +34,7 @@ use lemmy_db::{
post_view::PostView,
Crud,
};
use lemmy_utils::location_info;
pub async fn receive_delete(
activity: AnyBase,
@ -40,7 +42,7 @@ pub async fn receive_delete(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(activity)?.unwrap();
let delete = Delete::from_any_base(activity)?.context(location_info!())?;
match delete.object().as_single_kind_str() {
Some("Page") => receive_delete_post(delete, client, pool, chat_server).await,
Some("Note") => receive_delete_comment(delete, client, pool, chat_server).await,
@ -56,7 +58,8 @@ async fn receive_delete_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&delete, client, pool).await?;
let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?))
.await?
@ -110,7 +113,8 @@ async fn receive_delete_comment(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&delete, client, pool).await?;
let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?))
.await?
@ -166,7 +170,8 @@ async fn receive_delete_community(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let user = get_user_from_activity(&delete, client, pool).await?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?))

View File

@ -21,6 +21,7 @@ use crate::{
};
use activitystreams::{activity::Dislike, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{
comment::{CommentForm, CommentLike, CommentLikeForm},
comment_view::CommentView,
@ -28,6 +29,7 @@ use lemmy_db::{
post_view::PostView,
Likeable,
};
use lemmy_utils::location_info;
pub async fn receive_dislike(
activity: AnyBase,
@ -35,7 +37,7 @@ pub async fn receive_dislike(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let dislike = Dislike::from_any_base(activity)?.unwrap();
let dislike = Dislike::from_any_base(activity)?.context(location_info!())?;
match dislike.object().as_single_kind_str() {
Some("Page") => receive_dislike_post(dislike, client, pool, chat_server).await,
Some("Note") => receive_dislike_comment(dislike, client, pool, chat_server).await,
@ -50,7 +52,14 @@ async fn receive_dislike_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&dislike, client, pool).await?;
let page = PageExt::from_any_base(dislike.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(
dislike
.object()
.to_owned()
.one()
.context(location_info!())?,
)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?;
@ -90,7 +99,14 @@ async fn receive_dislike_comment(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let note = Note::from_any_base(dislike.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(
dislike
.object()
.to_owned()
.one()
.context(location_info!())?,
)?
.context(location_info!())?;
let user = get_user_from_activity(&dislike, client, pool).await?;
let comment = CommentForm::from_apub(&note, client, pool, None).await?;

View File

@ -21,6 +21,7 @@ use crate::{
};
use activitystreams::{activity::Like, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{
comment::{CommentForm, CommentLike, CommentLikeForm},
comment_view::CommentView,
@ -28,6 +29,7 @@ use lemmy_db::{
post_view::PostView,
Likeable,
};
use lemmy_utils::location_info;
pub async fn receive_like(
activity: AnyBase,
@ -35,7 +37,7 @@ pub async fn receive_like(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let like = Like::from_any_base(activity)?.unwrap();
let like = Like::from_any_base(activity)?.context(location_info!())?;
match like.object().as_single_kind_str() {
Some("Page") => receive_like_post(like, client, pool, chat_server).await,
Some("Note") => receive_like_comment(like, client, pool, chat_server).await,
@ -50,7 +52,8 @@ async fn receive_like_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&like, client, pool).await?;
let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?;
@ -90,7 +93,8 @@ async fn receive_like_comment(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let user = get_user_from_activity(&like, client, pool).await?;
let comment = CommentForm::from_apub(&note, client, pool, None).await?;

View File

@ -24,7 +24,7 @@ use crate::{
};
use activitystreams::{activity::Remove, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse};
use anyhow::anyhow;
use anyhow::{anyhow, Context};
use lemmy_db::{
comment::{Comment, CommentForm},
comment_view::CommentView,
@ -35,6 +35,7 @@ use lemmy_db::{
post_view::PostView,
Crud,
};
use lemmy_utils::location_info;
pub async fn receive_remove(
activity: AnyBase,
@ -42,7 +43,7 @@ pub async fn receive_remove(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let remove = Remove::from_any_base(activity)?.unwrap();
let remove = Remove::from_any_base(activity)?.context(location_info!())?;
let actor = get_user_from_activity(&remove, client, pool).await?;
let community = get_community_id_from_activity(&remove)?;
if actor.actor_id()?.domain() != community.domain() {
@ -64,7 +65,8 @@ async fn receive_remove_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(&remove, client, pool).await?;
let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, None)
.await?
@ -118,7 +120,8 @@ async fn receive_remove_comment(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(&remove, client, pool).await?;
let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, None)
.await?
@ -175,7 +178,8 @@ async fn receive_remove_community(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(&remove, client, pool).await?;
let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?))
.await?

View File

@ -28,7 +28,7 @@ use activitystreams::{
prelude::*,
};
use actix_web::{client::Client, HttpResponse};
use anyhow::anyhow;
use anyhow::{anyhow, Context};
use lemmy_db::{
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
comment_view::CommentView,
@ -40,6 +40,7 @@ use lemmy_db::{
Crud,
Likeable,
};
use lemmy_utils::location_info;
pub async fn receive_undo(
activity: AnyBase,
@ -47,7 +48,7 @@ pub async fn receive_undo(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let undo = Undo::from_any_base(activity)?.unwrap();
let undo = Undo::from_any_base(activity)?.context(location_info!())?;
match undo.object().as_single_kind_str() {
Some("Delete") => receive_undo_delete(undo, client, pool, chat_server).await,
Some("Remove") => receive_undo_remove(undo, client, pool, chat_server).await,
@ -62,10 +63,14 @@ where
T: AsBase<A> + ActorAndObjectRef,
{
let outer_actor = outer_activity.actor()?;
let outer_actor_uri = outer_actor.as_single_xsd_any_uri().unwrap();
let outer_actor_uri = outer_actor
.as_single_xsd_any_uri()
.context(location_info!())?;
let inner_actor = inner_activity.actor()?;
let inner_actor_uri = inner_actor.as_single_xsd_any_uri().unwrap();
let inner_actor_uri = inner_actor
.as_single_xsd_any_uri()
.context(location_info!())?;
if outer_actor_uri.domain() != inner_actor_uri.domain() {
Err(anyhow!("Cant undo activities from a different instance").into())
@ -80,9 +85,13 @@ async fn receive_undo_delete(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
let delete = Delete::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &delete)?;
let type_ = delete.object().as_single_kind_str().unwrap();
let type_ = delete
.object()
.as_single_kind_str()
.context(location_info!())?;
match type_ {
"Note" => receive_undo_delete_comment(undo, &delete, client, pool, chat_server).await,
"Page" => receive_undo_delete_post(undo, &delete, client, pool, chat_server).await,
@ -97,10 +106,14 @@ async fn receive_undo_remove(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let remove = Remove::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
let remove = Remove::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &remove)?;
let type_ = remove.object().as_single_kind_str().unwrap();
let type_ = remove
.object()
.as_single_kind_str()
.context(location_info!())?;
match type_ {
"Note" => receive_undo_remove_comment(undo, &remove, client, pool, chat_server).await,
"Page" => receive_undo_remove_post(undo, &remove, client, pool, chat_server).await,
@ -115,10 +128,14 @@ async fn receive_undo_like(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let like = Like::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
let like = Like::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &like)?;
let type_ = like.object().as_single_kind_str().unwrap();
let type_ = like
.object()
.as_single_kind_str()
.context(location_info!())?;
match type_ {
"Note" => receive_undo_like_comment(undo, &like, client, pool, chat_server).await,
"Page" => receive_undo_like_post(undo, &like, client, pool, chat_server).await,
@ -132,12 +149,16 @@ async fn receive_undo_dislike(
_pool: &DbPool,
_chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let dislike = Dislike::from_any_base(undo.object().to_owned().one().unwrap())?.unwrap();
let dislike = Dislike::from_any_base(undo.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
check_is_undo_valid(&undo, &dislike)?;
// TODO: need to implement Undo<Dislike>
let type_ = dislike.object().as_single_kind_str().unwrap();
let type_ = dislike
.object()
.as_single_kind_str()
.context(location_info!())?;
Err(anyhow!("Undo Delete type {} not supported", type_).into())
}
@ -149,7 +170,8 @@ async fn receive_undo_delete_comment(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(delete, client, pool).await?;
let note = Note::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?))
.await?
@ -207,7 +229,8 @@ async fn receive_undo_remove_comment(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(remove, client, pool).await?;
let note = Note::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment_ap_id = CommentForm::from_apub(&note, client, pool, None)
.await?
@ -265,7 +288,8 @@ async fn receive_undo_delete_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(delete, client, pool).await?;
let page = PageExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?))
.await?
@ -320,7 +344,8 @@ async fn receive_undo_remove_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(remove, client, pool).await?;
let page = PageExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post_ap_id = PostForm::from_apub(&page, client, pool, None)
.await?
@ -375,7 +400,8 @@ async fn receive_undo_delete_community(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(delete, client, pool).await?;
let group = GroupExt::from_any_base(delete.object().to_owned().one().unwrap())?.unwrap();
let group = GroupExt::from_any_base(delete.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(user.actor_id()?))
.await?
@ -441,7 +467,8 @@ async fn receive_undo_remove_community(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let mod_ = get_user_from_activity(remove, client, pool).await?;
let group = GroupExt::from_any_base(remove.object().to_owned().one().unwrap())?.unwrap();
let group = GroupExt::from_any_base(remove.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let community_actor_id = CommunityForm::from_apub(&group, client, pool, Some(mod_.actor_id()?))
.await?
@ -507,7 +534,8 @@ async fn receive_undo_like_comment(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(like, client, pool).await?;
let note = Note::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let comment = CommentForm::from_apub(&note, client, pool, None).await?;
@ -553,7 +581,8 @@ async fn receive_undo_like_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(like, client, pool).await?;
let page = PageExt::from_any_base(like.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(like.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, None).await?;

View File

@ -25,6 +25,7 @@ use crate::{
};
use activitystreams::{activity::Update, base::AnyBase, object::Note, prelude::*};
use actix_web::{client::Client, HttpResponse};
use anyhow::Context;
use lemmy_db::{
comment::{Comment, CommentForm},
comment_view::CommentView,
@ -32,7 +33,7 @@ use lemmy_db::{
post_view::PostView,
Crud,
};
use lemmy_utils::scrape_text_for_mentions;
use lemmy_utils::{location_info, scrape_text_for_mentions};
pub async fn receive_update(
activity: AnyBase,
@ -40,11 +41,11 @@ pub async fn receive_update(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let update = Update::from_any_base(activity)?.unwrap();
let update = Update::from_any_base(activity)?.context(location_info!())?;
// ensure that update and actor come from the same instance
let user = get_user_from_activity(&update, client, pool).await?;
update.id(user.actor_id()?.domain().unwrap())?;
update.id(user.actor_id()?.domain().context(location_info!())?)?;
match update.object().as_single_kind_str() {
Some("Page") => receive_update_post(update, client, pool, chat_server).await,
@ -60,7 +61,8 @@ async fn receive_update_post(
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let user = get_user_from_activity(&update, client, pool).await?;
let page = PageExt::from_any_base(update.object().to_owned().one().unwrap())?.unwrap();
let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let post = PostForm::from_apub(&page, client, pool, Some(user.actor_id()?)).await?;
@ -97,7 +99,8 @@ async fn receive_update_comment(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let note = Note::from_any_base(update.object().to_owned().one().unwrap())?.unwrap();
let note = Note::from_any_base(update.object().to_owned().one().context(location_info!())?)?
.context(location_info!())?;
let user = get_user_from_activity(&update, client, pool).await?;
let comment = CommentForm::from_apub(&note, client, pool, Some(user.actor_id()?)).await?;

View File

@ -16,12 +16,13 @@ use activitystreams::{
prelude::*,
};
use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use anyhow::anyhow;
use anyhow::{anyhow, Context};
use lemmy_db::{
community::{Community, CommunityFollower, CommunityFollowerForm},
user::User_,
Followable,
};
use lemmy_utils::location_info;
use log::debug;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
@ -62,7 +63,10 @@ pub async fn community_inbox(
"Community {} received activity {:?}",
&community.name, &activity
);
let user_uri = activity.actor()?.as_single_xsd_any_uri().unwrap();
let user_uri = activity
.actor()?
.as_single_xsd_any_uri()
.context(location_info!())?;
check_is_apub_id_valid(user_uri)?;
let user = get_or_fetch_and_upsert_user(&user_uri, &client, &db).await?;
@ -70,7 +74,7 @@ pub async fn community_inbox(
verify(&request, &user)?;
let any_base = activity.clone().into_any_base()?;
let kind = activity.kind().unwrap();
let kind = activity.kind().context(location_info!())?;
let user_id = user.id;
let res = match kind {
ValidTypes::Follow => handle_follow(any_base, user, community, &client, &db).await,
@ -90,7 +94,7 @@ async fn handle_follow(
client: &Client,
db: &DbPoolParam,
) -> Result<HttpResponse, LemmyError> {
let follow = Follow::from_any_base(activity)?.unwrap();
let follow = Follow::from_any_base(activity)?.context(location_info!())?;
let community_follower_form = CommunityFollowerForm {
community_id: community.id,
user_id: user.id,
@ -113,7 +117,7 @@ async fn handle_undo_follow(
community: Community,
db: &DbPoolParam,
) -> Result<HttpResponse, LemmyError> {
let _undo = Undo::from_any_base(activity)?.unwrap();
let _undo = Undo::from_any_base(activity)?.context(location_info!())?;
let community_follower_form = CommunityFollowerForm {
community_id: community.id,

View File

@ -31,7 +31,9 @@ use activitystreams::{
prelude::*,
};
use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use anyhow::Context;
use lemmy_db::user::User_;
use lemmy_utils::location_info;
use log::debug;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
@ -67,7 +69,11 @@ pub async fn shared_inbox(
let json = serde_json::to_string(&activity)?;
debug!("Shared inbox received activity: {}", json);
let sender = &activity.actor()?.to_owned().single_xsd_any_uri().unwrap();
let sender = &activity
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let community = get_community_id_from_activity(&activity)?;
check_is_apub_id_valid(sender)?;
@ -77,7 +83,7 @@ pub async fn shared_inbox(
verify(&request, actor.as_ref())?;
let any_base = activity.clone().into_any_base()?;
let kind = activity.kind().unwrap();
let kind = activity.kind().context(location_info!())?;
let res = match kind {
ValidTypes::Announce => receive_announce(any_base, &client, &pool, chat_server).await,
ValidTypes::Create => receive_create(any_base, &client, &pool, chat_server).await,
@ -112,7 +118,7 @@ where
T: AsBase<A> + ActorAndObjectRef,
{
let actor = activity.actor()?;
let user_uri = actor.as_single_xsd_any_uri().unwrap();
let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?;
get_or_fetch_and_upsert_user(&user_uri, client, pool).await
}
@ -122,9 +128,15 @@ pub(in crate::apub::inbox) fn get_community_id_from_activity<T, A>(
where
T: AsBase<A> + ActorAndObjectRef + AsObject<A>,
{
let cc = activity.cc().unwrap();
let cc = cc.as_many().unwrap();
Ok(cc.first().unwrap().as_xsd_any_uri().unwrap().to_owned())
let cc = activity.cc().context(location_info!())?;
let cc = cc.as_many().context(location_info!())?;
Ok(
cc.first()
.context(location_info!())?
.as_xsd_any_uri()
.context(location_info!())?
.to_owned(),
)
}
pub(in crate::apub::inbox) async fn announce_if_community_is_local<T, Kind>(
@ -139,9 +151,13 @@ where
Kind: Serialize,
<T as Extends<Kind>>::Error: From<serde_json::Error> + Send + Sync + 'static,
{
let cc = activity.cc().unwrap();
let cc = cc.as_many().unwrap();
let community_followers_uri = cc.first().unwrap().as_xsd_any_uri().unwrap();
let cc = activity.cc().context(location_info!())?;
let cc = cc.as_many().context(location_info!())?;
let community_followers_uri = cc
.first()
.context(location_info!())?
.as_xsd_any_uri()
.context(location_info!())?;
// TODO: this is hacky but seems to be the only way to get the community ID
let community_uri = community_followers_uri
.to_string()

View File

@ -20,6 +20,7 @@ use activitystreams::{
prelude::*,
};
use actix_web::{client::Client, web, HttpRequest, HttpResponse};
use anyhow::Context;
use lemmy_db::{
community::{CommunityFollower, CommunityFollowerForm},
naive_now,
@ -29,6 +30,7 @@ use lemmy_db::{
Crud,
Followable,
};
use lemmy_utils::location_info;
use log::debug;
use serde::{Deserialize, Serialize};
use std::fmt::Debug;
@ -58,7 +60,10 @@ pub async fn user_inbox(
let username = path.into_inner();
debug!("User {} received activity: {:?}", &username, &activity);
let actor_uri = activity.actor()?.as_single_xsd_any_uri().unwrap();
let actor_uri = activity
.actor()?
.as_single_xsd_any_uri()
.context(location_info!())?;
check_is_apub_id_valid(actor_uri)?;
@ -66,7 +71,7 @@ pub async fn user_inbox(
verify(&request, actor.as_ref())?;
let any_base = activity.clone().into_any_base()?;
let kind = activity.kind().unwrap();
let kind = activity.kind().context(location_info!())?;
let res = match kind {
ValidTypes::Accept => receive_accept(any_base, username, &client, &pool).await,
ValidTypes::Create => {
@ -94,8 +99,12 @@ async fn receive_accept(
client: &Client,
pool: &DbPool,
) -> Result<HttpResponse, LemmyError> {
let accept = Accept::from_any_base(activity)?.unwrap();
let community_uri = accept.actor()?.to_owned().single_xsd_any_uri().unwrap();
let accept = Accept::from_any_base(activity)?.context(location_info!())?;
let community_uri = accept
.actor()?
.to_owned()
.single_xsd_any_uri()
.context(location_info!())?;
let community = get_or_fetch_and_upsert_community(&community_uri, client, pool).await?;
@ -123,10 +132,17 @@ async fn receive_create_private_message(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let create = Create::from_any_base(activity)?.unwrap();
let note = Note::from_any_base(create.object().as_one().unwrap().to_owned())?.unwrap();
let create = Create::from_any_base(activity)?.context(location_info!())?;
let note = Note::from_any_base(
create
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(create.id_unchecked().unwrap().to_owned());
let domain = Some(create.id_unchecked().context(location_info!())?.to_owned());
let private_message = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let inserted_private_message = blocking(pool, move |conn| {
@ -159,10 +175,17 @@ async fn receive_update_private_message(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let update = Update::from_any_base(activity)?.unwrap();
let note = Note::from_any_base(update.object().as_one().unwrap().to_owned())?.unwrap();
let update = Update::from_any_base(activity)?.context(location_info!())?;
let note = Note::from_any_base(
update
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(update.id_unchecked().unwrap().to_owned());
let domain = Some(update.id_unchecked().context(location_info!())?.to_owned());
let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let private_message_ap_id = private_message_form.ap_id.clone();
@ -203,10 +226,17 @@ async fn receive_delete_private_message(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let delete = Delete::from_any_base(activity)?.unwrap();
let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap();
let delete = Delete::from_any_base(activity)?.context(location_info!())?;
let note = Note::from_any_base(
delete
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(delete.id_unchecked().unwrap().to_owned());
let domain = Some(delete.id_unchecked().context(location_info!())?.to_owned());
let private_message_form = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let private_message_ap_id = private_message_form.ap_id;
@ -259,11 +289,19 @@ async fn receive_undo_delete_private_message(
pool: &DbPool,
chat_server: ChatServerParam,
) -> Result<HttpResponse, LemmyError> {
let undo = Undo::from_any_base(activity)?.unwrap();
let delete = Delete::from_any_base(undo.object().as_one().unwrap().to_owned())?.unwrap();
let note = Note::from_any_base(delete.object().as_one().unwrap().to_owned())?.unwrap();
let undo = Undo::from_any_base(activity)?.context(location_info!())?;
let delete = Delete::from_any_base(undo.object().as_one().context(location_info!())?.to_owned())?
.context(location_info!())?;
let note = Note::from_any_base(
delete
.object()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?;
let domain = Some(undo.id_unchecked().unwrap().to_owned());
let domain = Some(undo.id_unchecked().context(location_info!())?.to_owned());
let private_message = PrivateMessageForm::from_apub(&note, client, pool, domain).await?;
let private_message_ap_id = private_message.ap_id.clone();

View File

@ -30,10 +30,16 @@ use activitystreams::{
};
use activitystreams_ext::{Ext1, Ext2};
use actix_web::{body::Body, client::Client, HttpResponse};
use anyhow::anyhow;
use anyhow::{anyhow, Context};
use chrono::NaiveDateTime;
use lemmy_db::{activity::do_insert_activity, user::User_};
use lemmy_utils::{convert_datetime, get_apub_protocol_string, settings::Settings, MentionData};
use lemmy_utils::{
convert_datetime,
get_apub_protocol_string,
location_info,
settings::Settings,
MentionData,
};
use log::debug;
use serde::Serialize;
use url::{ParseError, Url};
@ -80,7 +86,12 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
// instance. replace is needed to remove the port in our federation test setup.
let settings = Settings::get();
let local_instance = settings.hostname.split(':').collect::<Vec<&str>>();
allowed_instances.push(local_instance.first().unwrap().to_string());
allowed_instances.push(
local_instance
.first()
.context(location_info!())?
.to_string(),
);
match apub_id.domain() {
Some(d) => {
@ -197,10 +208,10 @@ where
T: Base + AsBase<Kind>,
{
let actor_id = if let Some(url) = expected_domain {
let domain = url.domain().unwrap();
apub.id(domain)?.unwrap()
let domain = url.domain().context(location_info!())?;
apub.id(domain)?.context(location_info!())?
} else {
let actor_id = apub.id_unchecked().unwrap();
let actor_id = apub.id_unchecked().context(location_info!())?;
check_is_apub_id_valid(&actor_id)?;
actor_id
};
@ -229,25 +240,13 @@ pub trait ApubLikeableType {
) -> Result<(), LemmyError>;
}
pub fn get_shared_inbox(actor_id: &Url) -> String {
format!(
"{}://{}{}/inbox",
&actor_id.scheme(),
&actor_id.host_str().unwrap(),
if let Some(port) = actor_id.port() {
format!(":{}", port)
} else {
"".to_string()
},
)
}
#[async_trait::async_trait(?Send)]
pub trait ActorType {
fn actor_id_str(&self) -> String;
fn public_key(&self) -> String;
fn private_key(&self) -> String;
// TODO: every actor should have a public key, so this shouldnt be an option (needs to be fixed in db)
fn public_key(&self) -> Option<String>;
fn private_key(&self) -> Option<String>;
/// numeric id in the database, used for insert_activity
fn user_id(&self) -> i32;
@ -257,13 +256,13 @@ pub trait ActorType {
#[allow(unused_variables)]
async fn send_follow(
&self,
follow_actor_id: &str,
follow_actor_id: &Url,
client: &Client,
pool: &DbPool,
) -> Result<(), LemmyError>;
async fn send_unfollow(
&self,
follow_actor_id: &str,
follow_actor_id: &Url,
client: &Client,
pool: &DbPool,
) -> Result<(), LemmyError>;
@ -303,7 +302,7 @@ pub trait ActorType {
) -> Result<(), LemmyError>;
/// For a given community, returns the inboxes of all followers.
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<String>, LemmyError>;
async fn get_follower_inboxes(&self, pool: &DbPool) -> Result<Vec<Url>, LemmyError>;
fn actor_id(&self) -> Result<Url, ParseError> {
Url::parse(&self.actor_id_str())
@ -314,9 +313,19 @@ pub trait ActorType {
Url::parse(&format!("{}/inbox", &self.actor_id_str()))
}
// TODO: make this return `Result<Url, ParseError>
fn get_shared_inbox_url(&self) -> String {
get_shared_inbox(&self.actor_id().unwrap())
fn get_shared_inbox_url(&self) -> Result<Url, LemmyError> {
let actor_id = self.actor_id()?;
let url = format!(
"{}://{}{}/inbox",
&actor_id.scheme(),

Cool, so we do get some url functionality out of this.

Cool, so we do get some url functionality out of this.

What do you mean get some url functionality?

What do you mean get some url functionality?
&actor_id.host_str().context(location_info!())?,
if let Some(port) = actor_id.port() {
format!(":{}", port)
} else {
"".to_string()
},
);
Ok(Url::parse(&url)?)
}
fn get_outbox_url(&self) -> Result<Url, ParseError> {
@ -335,13 +344,15 @@ pub trait ActorType {
format!("{}/liked", &self.actor_id_str())
}
fn get_public_key_ext(&self) -> PublicKeyExtension {
PublicKey {
id: format!("{}#main-key", self.actor_id_str()),
owner: self.actor_id_str(),
public_key_pem: self.public_key(),
}
.to_ext()
fn get_public_key_ext(&self) -> Result<PublicKeyExtension, LemmyError> {
Ok(
PublicKey {
id: format!("{}#main-key", self.actor_id_str()),
owner: self.actor_id_str(),
public_key_pem: self.public_key().context(location_info!())?,

Nice, this is a pretty easy way to do this.

Nice, this is a pretty easy way to do this.
}
.to_ext(),
)
}
}

View File

@ -32,19 +32,20 @@ use activitystreams::{
Update,
},
context,
object::{kind::PageType, Image, Page, Tombstone},
object::{kind::PageType, Image, Object, Page, Tombstone},
prelude::*,
public,
};
use activitystreams_ext::Ext1;
use actix_web::{body::Body, client::Client, web, HttpResponse};
use anyhow::Context;
use lemmy_db::{
community::Community,
post::{Post, PostForm},
user::User_,
Crud,
};
use lemmy_utils::{convert_datetime, remove_slurs};
use lemmy_utils::{convert_datetime, location_info, remove_slurs};
use serde::Deserialize;
use url::Url;
@ -147,6 +148,50 @@ impl ToApub for Post {
}
}
struct EmbedType {

Is it possible to do this as a struct?

struct EmbedType {
  name: Option...
  summary:...
  content:...

Its a preference thing, but I really don't like tuple structs, and want to eliminate any others if we have them. You have to guess what that 2nd or 3rd item is, whereas with the regular structs, its a named thing so you know what it is.

Is it possible to do this as a struct? ``` struct EmbedType { name: Option... summary:... content:... ``` Its a preference thing, but I really don't like tuple structs, and want to eliminate any others if we have them. You have to guess what that 2nd or 3rd item is, whereas with the regular structs, its a named thing so you know what it is.

Sure I can do that, just added the typedef cause clippy was complaining.

Sure I can do that, just added the typedef cause clippy was complaining.
title: Option<String>,
description: Option<String>,
html: Option<String>,
}
fn extract_embed_from_apub(
page: &Ext1<Object<PageType>, PageExtension>,
) -> Result<EmbedType, LemmyError> {
match page.inner.preview() {
Some(preview) => {
let preview_page = Page::from_any_base(preview.one().context(location_info!())?.to_owned())?
.context(location_info!())?;
let title = preview_page
.name()
.map(|n| n.one())
.flatten()
.map(|s| s.as_xsd_string())
.flatten()
.map(|s| s.to_string());
let description = preview_page
.summary()
.map(|s| s.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
let html = preview_page
.content()
.map(|c| c.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
Ok(EmbedType {
title,
description,
html,
})
}
None => Ok(EmbedType {
title: None,
description: None,
html: None,
}),
}
}
#[async_trait::async_trait(?Send)]
impl FromApub for PostForm {
type ApubType = PageExt;
@ -163,9 +208,9 @@ impl FromApub for PostForm {
.inner
.attributed_to()
.as_ref()
.unwrap()
.context(location_info!())?
.as_single_xsd_any_uri()
.unwrap();
.context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(creator_actor_id, client, pool).await?;
@ -173,57 +218,52 @@ impl FromApub for PostForm {
.inner
.to()
.as_ref()
.unwrap()
.context(location_info!())?
.as_single_xsd_any_uri()
.unwrap();
.context(location_info!())?;
let community = get_or_fetch_and_upsert_community(community_actor_id, client, pool).await?;
let thumbnail_url = match &page.inner.image() {
Some(any_image) => Image::from_any_base(any_image.to_owned().as_one().unwrap().to_owned())?
.unwrap()
.url()
.unwrap()
.as_single_xsd_any_uri()
.map(|u| u.to_string()),
Some(any_image) => Image::from_any_base(
any_image
.to_owned()
.as_one()
.context(location_info!())?
.to_owned(),
)?
.context(location_info!())?
.url()
.context(location_info!())?
.as_single_xsd_any_uri()
.map(|u| u.to_string()),
None => None,
};
let (embed_title, embed_description, embed_html) = match page.inner.preview() {
Some(preview) => {
let preview_page = Page::from_any_base(preview.one().unwrap().to_owned())?.unwrap();
let name = preview_page
.name()
.map(|n| n.as_one().unwrap().as_xsd_string().unwrap().to_string());
let summary = preview_page
.summary()
.map(|s| s.as_single_xsd_string().unwrap().to_string());
let content = preview_page
.content()
.map(|c| c.as_single_xsd_string().unwrap().to_string());
(name, summary, content)
}
None => (None, None, None),
};
let embed = extract_embed_from_apub(page)?;
let name = page
.inner
.summary()
.as_ref()
.unwrap()
.context(location_info!())?
.as_single_xsd_string()
.unwrap()
.context(location_info!())?
.to_string();
let url = page
.inner
.url()
.as_ref()
.map(|u| u.as_single_xsd_string().unwrap().to_string());
.map(|u| u.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
let body = page
.inner
.content()
.as_ref()
.map(|c| c.as_single_xsd_string().unwrap().to_string());
.map(|c| c.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
check_slurs(&name)?;
let body_slurs_removed = body.map(|b| remove_slurs(&b));
Ok(PostForm {
@ -247,9 +287,9 @@ impl FromApub for PostForm {
deleted: None,
nsfw: ext.sensitive,
stickied: Some(ext.stickied),
embed_title,
embed_description,
embed_html,
embed_title: embed.title,
embed_description: embed.description,
embed_html: embed.html,
thumbnail_url,
ap_id: check_actor_domain(page, expected_domain)?,
local: false,
@ -281,7 +321,7 @@ impl ApubObjectType for Post {
send_activity_to_community(
creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
create.into_any_base()?,
client,
pool,
@ -312,7 +352,7 @@ impl ApubObjectType for Post {
send_activity_to_community(
creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
update.into_any_base()?,
client,
pool,
@ -342,7 +382,7 @@ impl ApubObjectType for Post {
send_activity_to_community(
creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
delete.into_any_base()?,
client,
pool,
@ -380,7 +420,7 @@ impl ApubObjectType for Post {
send_activity_to_community(
creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
undo.into_any_base()?,
client,
pool,
@ -410,7 +450,7 @@ impl ApubObjectType for Post {
send_activity_to_community(
mod_,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
remove.into_any_base()?,
client,
pool,
@ -448,7 +488,7 @@ impl ApubObjectType for Post {
send_activity_to_community(
mod_,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
undo.into_any_base()?,
client,
pool,
@ -481,7 +521,7 @@ impl ApubLikeableType for Post {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
like.into_any_base()?,
client,
pool,
@ -511,7 +551,7 @@ impl ApubLikeableType for Post {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
dislike.into_any_base()?,
client,
pool,
@ -549,7 +589,7 @@ impl ApubLikeableType for Post {
send_activity_to_community(
&creator,
&community,
vec![community.get_shared_inbox_url()],
vec![community.get_shared_inbox_url()?],
undo.into_any_base()?,
client,
pool,

View File

@ -6,6 +6,7 @@ use crate::{
create_tombstone,
fetcher::get_or_fetch_and_upsert_user,
insert_activity,
ActorType,
ApubObjectType,
FromApub,
ToApub,
@ -27,12 +28,13 @@ use activitystreams::{
prelude::*,
};
use actix_web::client::Client;
use anyhow::Context;
use lemmy_db::{
private_message::{PrivateMessage, PrivateMessageForm},
user::User_,
Crud,
};
use lemmy_utils::convert_datetime;
use lemmy_utils::{convert_datetime, location_info};
use url::Url;
#[async_trait::async_trait(?Send)]
@ -81,15 +83,20 @@ impl FromApub for PrivateMessageForm {
) -> Result<PrivateMessageForm, LemmyError> {
let creator_actor_id = note
.attributed_to()
.unwrap()
.context(location_info!())?
.clone()
.single_xsd_any_uri()
.unwrap();
.context(location_info!())?;
let creator = get_or_fetch_and_upsert_user(&creator_actor_id, client, pool).await?;
let recipient_actor_id = note.to().unwrap().clone().single_xsd_any_uri().unwrap();
let recipient_actor_id = note
.to()
.context(location_info!())?
.clone()
.single_xsd_any_uri()
.context(location_info!())?;
let recipient = get_or_fetch_and_upsert_user(&recipient_actor_id, client, pool).await?;
let ap_id = note.id_unchecked().unwrap().to_string();
let ap_id = note.id_unchecked().context(location_info!())?.to_string();
check_is_apub_id_valid(&Url::parse(&ap_id)?)?;
Ok(PrivateMessageForm {
@ -97,9 +104,9 @@ impl FromApub for PrivateMessageForm {
recipient_id: recipient.id,
content: note
.content()
.unwrap()
.context(location_info!())?
.as_single_xsd_string()
.unwrap()
.context(location_info!())?
.to_string(),
published: note.published().map(|u| u.to_owned().naive_local()),
updated: note.updated().map(|u| u.to_owned().naive_local()),
@ -126,7 +133,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut create = Create::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id);
let to = recipient.get_inbox_url()?;
create
.set_context(context())
.set_id(generate_activity_id(CreateType::Create)?)
@ -151,7 +158,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut update = Update::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id);
let to = recipient.get_inbox_url()?;
update
.set_context(context())
.set_id(generate_activity_id(UpdateType::Update)?)
@ -175,7 +182,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id);
let to = recipient.get_inbox_url()?;
delete
.set_context(context())
.set_id(generate_activity_id(DeleteType::Delete)?)
@ -199,7 +206,7 @@ impl ApubObjectType for PrivateMessage {
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
let mut delete = Delete::new(creator.actor_id.to_owned(), note.into_any_base()?);
let to = format!("{}/inbox", recipient.actor_id);
let to = recipient.get_inbox_url()?;
delete
.set_context(context())
.set_id(generate_activity_id(DeleteType::Delete)?)

View File

@ -4,6 +4,7 @@ use crate::{
activities::{generate_activity_id, send_activity},
check_actor_domain,
create_apub_response,
fetcher::get_or_fetch_and_upsert_actor,
insert_activity,
ActorType,
FromApub,
@ -28,11 +29,12 @@ use activitystreams::{
};
use activitystreams_ext::Ext1;
use actix_web::{body::Body, client::Client, web, HttpResponse};
use anyhow::Context;
use lemmy_db::{
naive_now,
user::{UserForm, User_},
};
use lemmy_utils::convert_datetime;
use lemmy_utils::{convert_datetime, location_info};
use serde::Deserialize;
use url::Url;
@ -82,7 +84,7 @@ impl ToApub for User_ {
.set_following(self.get_following_url().parse()?)
.set_liked(self.get_liked_url().parse()?)
.set_endpoints(Endpoints {
shared_inbox: Some(self.get_shared_inbox_url().parse()?),
shared_inbox: Some(self.get_shared_inbox_url()?),
..Default::default()
});
@ -90,7 +92,7 @@ impl ToApub for User_ {
ap_actor.set_preferred_username(i.to_owned());
}
Ok(Ext1::new(ap_actor, self.get_public_key_ext()))
Ok(Ext1::new(ap_actor, self.get_public_key_ext()?))
}
fn to_tombstone(&self) -> Result<Tombstone, LemmyError> {
unimplemented!()
@ -103,26 +105,27 @@ impl ActorType for User_ {
self.actor_id.to_owned()
}
fn public_key(&self) -> String {
self.public_key.to_owned().unwrap()
fn public_key(&self) -> Option<String> {
self.public_key.to_owned()
}
fn private_key(&self) -> String {
self.private_key.to_owned().unwrap()
fn private_key(&self) -> Option<String> {
self.private_key.to_owned()
}
/// As a given local user, send out a follow request to a remote community.
async fn send_follow(
&self,
follow_actor_id: &str,
follow_actor_id: &Url,
client: &Client,
pool: &DbPool,
) -> Result<(), LemmyError> {
let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id);
let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id.as_str());
follow
.set_context(context())
.set_id(generate_activity_id(FollowType::Follow)?);
let to = format!("{}/inbox", follow_actor_id);
let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, client, pool).await?;
let to = follow_actor.get_inbox_url()?;
insert_activity(self.id, follow.clone(), true, pool).await?;
@ -132,16 +135,17 @@ impl ActorType for User_ {
async fn send_unfollow(
&self,
follow_actor_id: &str,
follow_actor_id: &Url,
client: &Client,
pool: &DbPool,
) -> Result<(), LemmyError> {
let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id);
let mut follow = Follow::new(self.actor_id.to_owned(), follow_actor_id.as_str());
follow
.set_context(context())
.set_id(generate_activity_id(FollowType::Follow)?);
let follow_actor = get_or_fetch_and_upsert_actor(follow_actor_id, client, pool).await?;
let to = format!("{}/inbox", follow_actor_id);
let to = follow_actor.get_inbox_url()?;
// Undo that fake activity
let mut undo = Undo::new(Url::parse(&self.actor_id)?, follow.into_any_base()?);
@ -200,7 +204,7 @@ impl ActorType for User_ {
unimplemented!()
}
async fn get_follower_inboxes(&self, _pool: &DbPool) -> Result<Vec<String>, LemmyError> {
async fn get_follower_inboxes(&self, _pool: &DbPool) -> Result<Vec<Url>, LemmyError> {
unimplemented!()
}
@ -221,11 +225,10 @@ impl FromApub for UserForm {
) -> Result<Self, LemmyError> {
let avatar = match person.icon() {
Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone())
.unwrap()
.unwrap()
Image::from_any_base(any_image.as_one().context(location_info!())?.clone())?
.context(location_info!())?
.url()
.unwrap()
.context(location_info!())?
.as_single_xsd_any_uri()
.map(|u| u.to_string()),
),
@ -234,11 +237,11 @@ impl FromApub for UserForm {
let banner = match person.image() {
Some(any_image) => Some(
Image::from_any_base(any_image.as_one().unwrap().clone())
.unwrap()
.unwrap()
Image::from_any_base(any_image.as_one().context(location_info!())?.clone())
.context(location_info!())?
.context(location_info!())?
.url()
.unwrap()
.context(location_info!())?
.as_single_xsd_any_uri()
.map(|u| u.to_string()),
),
@ -247,17 +250,19 @@ impl FromApub for UserForm {
let name = person
.name()
.unwrap()
.context(location_info!())?
.one()
.unwrap()
.context(location_info!())?
.as_xsd_string()
.unwrap()
.context(location_info!())?
.to_string();
let preferred_username = person.inner.preferred_username().map(|u| u.to_string());
let bio = person
.inner
.summary()
.map(|s| s.as_single_xsd_string().unwrap().into());
.map(|s| s.as_single_xsd_string())
.flatten()
.map(|s| s.to_string());
check_slurs(&name)?;
check_slurs_opt(&preferred_username)?;
check_slurs_opt(&bio)?;