]> Untitled Git - lemmy.git/blob - crates/apub/src/objects/mod.rs
76c258ce27ab444f3416fe874b263fdb650682be
[lemmy.git] / crates / apub / src / objects / mod.rs
1 use activitystreams::{
2   base::BaseExt,
3   object::{kind::ImageType, Tombstone, TombstoneExt},
4 };
5 use anyhow::anyhow;
6 use chrono::NaiveDateTime;
7 use html2md::parse_html;
8 use lemmy_apub_lib::values::MediaTypeMarkdown;
9 use lemmy_utils::{utils::convert_datetime, LemmyError};
10 use serde::{Deserialize, Serialize};
11 use url::Url;
12
13 pub mod comment;
14 pub mod community;
15 pub mod person;
16 pub mod post;
17 pub mod private_message;
18
19 #[derive(Clone, Debug, Deserialize, Serialize)]
20 #[serde(rename_all = "camelCase")]
21 pub struct Source {
22   content: String,
23   media_type: MediaTypeMarkdown,
24 }
25
26 #[derive(Clone, Debug, Deserialize, Serialize)]
27 #[serde(rename_all = "camelCase")]
28 pub struct ImageObject {
29   #[serde(rename = "type")]
30   kind: ImageType,
31   url: Url,
32 }
33
34 /// Updated is actually the deletion time
35 fn create_tombstone<T>(
36   deleted: bool,
37   object_id: Url,
38   updated: Option<NaiveDateTime>,
39   former_type: T,
40 ) -> Result<Tombstone, LemmyError>
41 where
42   T: ToString,
43 {
44   if deleted {
45     if let Some(updated) = updated {
46       let mut tombstone = Tombstone::new();
47       tombstone.set_id(object_id);
48       tombstone.set_former_type(former_type.to_string());
49       tombstone.set_deleted(convert_datetime(updated));
50       Ok(tombstone)
51     } else {
52       Err(anyhow!("Cant convert to tombstone because updated time was None.").into())
53     }
54   } else {
55     Err(anyhow!("Cant convert object to tombstone if it wasnt deleted").into())
56   }
57 }
58
59 fn get_summary_from_string_or_source(
60   raw: &Option<String>,
61   source: &Option<Source>,
62 ) -> Option<String> {
63   if let Some(source) = &source {
64     Some(source.content.clone())
65   } else {
66     raw.as_ref().map(|s| parse_html(s))
67   }
68 }
69
70 #[cfg(test)]
71 mod tests {
72   use super::*;
73   use actix::Actor;
74   use diesel::{
75     r2d2::{ConnectionManager, Pool},
76     PgConnection,
77   };
78   use lemmy_apub_lib::activity_queue::create_activity_queue;
79   use lemmy_db_schema::{
80     establish_unpooled_connection,
81     get_database_url_from_env,
82     source::secret::Secret,
83   };
84   use lemmy_utils::{
85     rate_limit::{rate_limiter::RateLimiter, RateLimit},
86     request::build_user_agent,
87     settings::structs::Settings,
88   };
89   use lemmy_websocket::{chat_server::ChatServer, LemmyContext};
90   use reqwest::Client;
91   use serde::de::DeserializeOwned;
92   use std::{fs::File, io::BufReader, sync::Arc};
93   use tokio::sync::Mutex;
94
95   // TODO: would be nice if we didnt have to use a full context for tests.
96   //       or at least write a helper function so this code is shared with main.rs
97   pub(crate) fn init_context() -> LemmyContext {
98     // call this to run migrations
99     establish_unpooled_connection();
100     let settings = Settings::init().unwrap();
101     let rate_limiter = RateLimit {
102       rate_limiter: Arc::new(Mutex::new(RateLimiter::default())),
103       rate_limit_config: settings.rate_limit.to_owned().unwrap_or_default(),
104     };
105     let client = Client::builder()
106       .user_agent(build_user_agent(&settings))
107       .build()
108       .unwrap();
109     let activity_queue = create_activity_queue();
110     let secret = Secret {
111       id: 0,
112       jwt_secret: "".to_string(),
113     };
114     let db_url = match get_database_url_from_env() {
115       Ok(url) => url,
116       Err(_) => settings.get_database_url(),
117     };
118     let manager = ConnectionManager::<PgConnection>::new(&db_url);
119     let pool = Pool::builder()
120       .max_size(settings.database.pool_size)
121       .build(manager)
122       .unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
123     async fn x() -> Result<String, LemmyError> {
124       Ok("".to_string())
125     }
126     let chat_server = ChatServer::startup(
127       pool.clone(),
128       rate_limiter,
129       |_, _, _, _| Box::pin(x()),
130       |_, _, _, _| Box::pin(x()),
131       client.clone(),
132       activity_queue.clone(),
133       settings.clone(),
134       secret.clone(),
135     )
136     .start();
137     LemmyContext::create(pool, chat_server, client, activity_queue, settings, secret)
138   }
139
140   pub(crate) fn file_to_json_object<T: DeserializeOwned>(path: &str) -> T {
141     let file = File::open(path).unwrap();
142     let reader = BufReader::new(file);
143     serde_json::from_reader(reader).unwrap()
144   }
145 }