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