]> Untitled Git - lemmy.git/commitdiff
Remove usage of Option::unwrap() in activitypub code (#80)
authornutomic <nutomic@noreply.yerbamate.dev>
Tue, 11 Aug 2020 14:31:05 +0000 (14:31 +0000)
committerdessalines <dessalines@noreply.yerbamate.dev>
Tue, 11 Aug 2020 14:31:05 +0000 (14:31 +0000)
Remove remaining usages of unwrap() from activitypub code

Remove most usage of Option::unwrap() from activitypub code

Co-authored-by: Felix Ableitner <me@nutomic.com>
Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/80

22 files changed:
server/lemmy_utils/src/lib.rs
server/src/api/community.rs
server/src/apub/activities.rs
server/src/apub/comment.rs
server/src/apub/community.rs
server/src/apub/extensions/signatures.rs
server/src/apub/fetcher.rs
server/src/apub/inbox/activities/announce.rs
server/src/apub/inbox/activities/create.rs
server/src/apub/inbox/activities/delete.rs
server/src/apub/inbox/activities/dislike.rs
server/src/apub/inbox/activities/like.rs
server/src/apub/inbox/activities/remove.rs
server/src/apub/inbox/activities/undo.rs
server/src/apub/inbox/activities/update.rs
server/src/apub/inbox/community_inbox.rs
server/src/apub/inbox/shared_inbox.rs
server/src/apub/inbox/user_inbox.rs
server/src/apub/mod.rs
server/src/apub/post.rs
server/src/apub/private_message.rs
server/src/apub/user.rs

index 6d851b0337bf39681501ed734713da061fc0be1b..fc50e199b7d2c18a8b960f423d13f1112dd580c0 100644 (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)
 }
index c716084841e83611c1119e3d83660613368459b0..fb153895f22fb20863f8464788ad7f0fe49aed75 100644 (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() {
index b5d6ce46476e9d4a1d2ee63a42ac138385139db8..6b6b17b86057995e2b83944bd20632c0ca02e738 100644 (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),
index fbec59051733e8610439e6d5d2c529795b88d2ef..d90d8227b3e423c42f9974f6f9af4f922b1c3553 100644 (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();
 
index 8b522b447a6dcd6bd20e66a84c96f74fff27d0c9..fb8ef9bc6507d458c42004922269408cbe737c1d 100644 (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?;
 
index efc8dccfc8c9f5c9f9c75ac20d2347c255462da9..96063d5e0bdd2bbe34823ce020bdab2b8006e4e3 100644 (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)?)?)
     })?;
 
index 9bb058cd7ad2c80b75e8f162357416e48235ffdc..55e0991b6cfeccba280bacf68caa32415316d4b6 100644 (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)
index 0ed04835f22b8f79ae845e8fe4e228e7ab8479b0..b7e9a71fc78d86c85987802a823cb357dc249db2 100644 (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,
index b45f489a44ec4db9774aa6e05a5aeaa5ecfb42d3..55bd85fb044d0e8d610e17f132103678a750ab9b 100644 (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?;
 
index 1a48931026c73aafe7a4fb248520ed199bbc3412..7a56eb45b119377120c243c83647873370e75672 100644 (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()?))
index 95e2438eff9ba7e07c57d7ad8958b98914aa894c..233c89d815534b87a9acebbf3b48c3d1b077cb60 100644 (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?;
index f2705f222f76461d1b68d22434bf7f2500c82116..db34190f27178d85a4358d775a882a038cc8b189 100644 (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?;
index f4869ae15929f5d0d56d40cb3d2fc29573ce3aea..4e93dab8a76385468fa4736901371dc5f593bc40 100644 (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?
index 34e9e2109b15ebad44ca76438901df0c6a2efaf3..457fef6d85e7272c40c6cfa5d34e180cc1628aba 100644 (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?;
 
index 6f2a6d56062a365007ecacbac51f159f2cb95af9..6cc6afc485dc05de503ff2c823b8cc69a93f14d6 100644 (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?;
index 8b257d479bb740ebe62dbabc0f1fa9686f22fe3d..49ba48b84c2112e9a50293520c92a01b27c7d95e 100644 (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,
index 8e1e3c44443ce250e6d53dcd449462f1542960dc..f971a507269c925c8f1a75783173bd79e0782220 100644 (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()
index b443b51c840fa870c2404847b42082fed9158683..66f09afbeecab5c2aff34194ba4194d9307f6cff 100644 (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 domain = Some(create.id_unchecked().unwrap().to_owned());
+  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().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 domain = Some(update.id_unchecked().unwrap().to_owned());
+  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().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 domain = Some(delete.id_unchecked().unwrap().to_owned());
+  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().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 domain = Some(undo.id_unchecked().unwrap().to_owned());
+  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().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();
index 69272b49e27703696d05d897472bc4a047023bcf..f67471982592e9b05d25e987800eb419a16eb18a 100644 (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(),
+      &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!())?,
+      }
+      .to_ext(),
+    )
   }
 }
 
index 8bd8364f120a379fec9a46c9c048d7ae8bd6b43d..caf8f076a3de20b5b80d8e80bea9e7496942203c 100644 (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 {
+  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,
index 23975c7c987f43039d4d206d9864dd8f4915d20c..743a484f20b27bc054514c3bd03741c03ab3a6d3 100644 (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)?)
index 58338ab4da3c93d77a25e6679fd9724af7fd9c39..5f80b48176fc1ebc79d2978261253824012ccf3d 100644 (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)?;