]> Untitled Git - lemmy.git/blob - crates/apub/src/fetcher/objects.rs
Split api crate into api_structs and api
[lemmy.git] / crates / apub / src / fetcher / objects.rs
1 use crate::{fetcher::fetch::fetch_remote_object, objects::FromApub, NoteExt, PageExt};
2 use anyhow::anyhow;
3 use diesel::result::Error::NotFound;
4 use lemmy_api_common::blocking;
5 use lemmy_db_queries::{ApubObject, Crud};
6 use lemmy_db_schema::source::{comment::Comment, post::Post};
7 use lemmy_utils::LemmyError;
8 use lemmy_websocket::LemmyContext;
9 use log::debug;
10 use url::Url;
11
12 /// Gets a post by its apub ID. If it exists locally, it is returned directly. Otherwise it is
13 /// pulled from its apub ID, inserted and returned.
14 ///
15 /// The parent community is also pulled if necessary. Comments are not pulled.
16 pub(crate) async fn get_or_fetch_and_insert_post(
17   post_ap_id: &Url,
18   context: &LemmyContext,
19   recursion_counter: &mut i32,
20 ) -> Result<Post, LemmyError> {
21   let post_ap_id_owned = post_ap_id.to_owned();
22   let post = blocking(context.pool(), move |conn| {
23     Post::read_from_apub_id(conn, &post_ap_id_owned.into())
24   })
25   .await?;
26
27   match post {
28     Ok(p) => Ok(p),
29     Err(NotFound {}) => {
30       debug!("Fetching and creating remote post: {}", post_ap_id);
31       let page =
32         fetch_remote_object::<PageExt>(context.client(), post_ap_id, recursion_counter).await?;
33       let post = Post::from_apub(
34         &page,
35         context,
36         post_ap_id.to_owned(),
37         recursion_counter,
38         false,
39       )
40       .await?;
41
42       Ok(post)
43     }
44     Err(e) => Err(e.into()),
45   }
46 }
47
48 /// Gets a comment by its apub ID. If it exists locally, it is returned directly. Otherwise it is
49 /// pulled from its apub ID, inserted and returned.
50 ///
51 /// The parent community, post and comment are also pulled if necessary.
52 pub(crate) async fn get_or_fetch_and_insert_comment(
53   comment_ap_id: &Url,
54   context: &LemmyContext,
55   recursion_counter: &mut i32,
56 ) -> Result<Comment, LemmyError> {
57   let comment_ap_id_owned = comment_ap_id.to_owned();
58   let comment = blocking(context.pool(), move |conn| {
59     Comment::read_from_apub_id(conn, &comment_ap_id_owned.into())
60   })
61   .await?;
62
63   match comment {
64     Ok(p) => Ok(p),
65     Err(NotFound {}) => {
66       debug!(
67         "Fetching and creating remote comment and its parents: {}",
68         comment_ap_id
69       );
70       let comment =
71         fetch_remote_object::<NoteExt>(context.client(), comment_ap_id, recursion_counter).await?;
72       let comment = Comment::from_apub(
73         &comment,
74         context,
75         comment_ap_id.to_owned(),
76         recursion_counter,
77         false,
78       )
79       .await?;
80
81       let post_id = comment.post_id;
82       let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
83       if post.locked {
84         return Err(anyhow!("Post is locked").into());
85       }
86
87       Ok(comment)
88     }
89     Err(e) => Err(e.into()),
90   }
91 }