You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

463 lines
14 KiB

  1. use super::*;
  2. impl ToApub for Comment {
  3. type Response = Note;
  4. fn to_apub(&self, conn: &PgConnection) -> Result<Note, Error> {
  5. let mut comment = Note::default();
  6. let oprops: &mut ObjectProperties = comment.as_mut();
  7. let creator = User_::read(&conn, self.creator_id)?;
  8. let post = Post::read(&conn, self.post_id)?;
  9. let community = Community::read(&conn, post.community_id)?;
  10. // Add a vector containing some important info to the "in_reply_to" field
  11. // [post_ap_id, Option(parent_comment_ap_id)]
  12. let mut in_reply_to_vec = vec![post.ap_id];
  13. if let Some(parent_id) = self.parent_id {
  14. let parent_comment = Comment::read(&conn, parent_id)?;
  15. in_reply_to_vec.push(parent_comment.ap_id);
  16. }
  17. oprops
  18. // Not needed when the Post is embedded in a collection (like for community outbox)
  19. .set_context_xsd_any_uri(context())?
  20. .set_id(self.ap_id.to_owned())?
  21. .set_published(convert_datetime(self.published))?
  22. .set_to_xsd_any_uri(community.actor_id)?
  23. .set_many_in_reply_to_xsd_any_uris(in_reply_to_vec)?
  24. .set_content_xsd_string(self.content.to_owned())?
  25. .set_attributed_to_xsd_any_uri(creator.actor_id)?;
  26. if let Some(u) = self.updated {
  27. oprops.set_updated(convert_datetime(u))?;
  28. }
  29. Ok(comment)
  30. }
  31. fn to_tombstone(&self) -> Result<Tombstone, Error> {
  32. create_tombstone(
  33. self.deleted,
  34. &self.ap_id,
  35. self.updated,
  36. NoteType.to_string(),
  37. )
  38. }
  39. }
  40. impl FromApub for CommentForm {
  41. type ApubType = Note;
  42. /// Parse an ActivityPub note received from another instance into a Lemmy comment
  43. fn from_apub(note: &Note, conn: &PgConnection) -> Result<CommentForm, Error> {
  44. let oprops = &note.object_props;
  45. let creator_actor_id = &oprops.get_attributed_to_xsd_any_uri().unwrap().to_string();
  46. let creator = get_or_fetch_and_upsert_remote_user(&creator_actor_id, &conn)?;
  47. let mut in_reply_tos = oprops.get_many_in_reply_to_xsd_any_uris().unwrap();
  48. let post_ap_id = in_reply_tos.next().unwrap().to_string();
  49. // The 2nd item, if it exists, is the parent comment apub_id
  50. let parent_id: Option<i32> = match in_reply_tos.next() {
  51. Some(parent_comment_uri) => {
  52. let parent_comment_uri_str = &parent_comment_uri.to_string();
  53. let parent_comment = Comment::read_from_apub_id(&conn, &parent_comment_uri_str)?;
  54. Some(parent_comment.id)
  55. }
  56. None => None,
  57. };
  58. let post = Post::read_from_apub_id(&conn, &post_ap_id)?;
  59. Ok(CommentForm {
  60. creator_id: creator.id,
  61. post_id: post.id,
  62. parent_id,
  63. content: oprops
  64. .get_content_xsd_string()
  65. .map(|c| c.to_string())
  66. .unwrap(),
  67. removed: None,
  68. read: None,
  69. published: oprops
  70. .get_published()
  71. .map(|u| u.as_ref().to_owned().naive_local()),
  72. updated: oprops
  73. .get_updated()
  74. .map(|u| u.as_ref().to_owned().naive_local()),
  75. deleted: None,
  76. ap_id: oprops.get_id().unwrap().to_string(),
  77. local: false,
  78. })
  79. }
  80. }
  81. impl ApubObjectType for Comment {
  82. /// Send out information about a newly created comment, to the followers of the community.
  83. fn send_create(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
  84. let note = self.to_apub(conn)?;
  85. let post = Post::read(&conn, self.post_id)?;
  86. let community = Community::read(conn, post.community_id)?;
  87. let id = format!("{}/create/{}", self.ap_id, uuid::Uuid::new_v4());
  88. let mut create = Create::new();
  89. populate_object_props(
  90. &mut create.object_props,
  91. &community.get_followers_url(),
  92. &id,
  93. )?;
  94. create
  95. .create_props
  96. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  97. .set_object_base_box(note)?;
  98. // Insert the sent activity into the activity table
  99. let activity_form = activity::ActivityForm {
  100. user_id: creator.id,
  101. data: serde_json::to_value(&create)?,
  102. local: true,
  103. updated: None,
  104. };
  105. activity::Activity::create(&conn, &activity_form)?;
  106. send_activity(
  107. &create,
  108. &creator.private_key.as_ref().unwrap(),
  109. &creator.actor_id,
  110. community.get_follower_inboxes(&conn)?,
  111. )?;
  112. Ok(())
  113. }
  114. /// Send out information about an edited post, to the followers of the community.
  115. fn send_update(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
  116. let note = self.to_apub(&conn)?;
  117. let post = Post::read(&conn, self.post_id)?;
  118. let community = Community::read(&conn, post.community_id)?;
  119. let id = format!("{}/update/{}", self.ap_id, uuid::Uuid::new_v4());
  120. let mut update = Update::new();
  121. populate_object_props(
  122. &mut update.object_props,
  123. &community.get_followers_url(),
  124. &id,
  125. )?;
  126. update
  127. .update_props
  128. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  129. .set_object_base_box(note)?;
  130. // Insert the sent activity into the activity table
  131. let activity_form = activity::ActivityForm {
  132. user_id: creator.id,
  133. data: serde_json::to_value(&update)?,
  134. local: true,
  135. updated: None,
  136. };
  137. activity::Activity::create(&conn, &activity_form)?;
  138. send_activity(
  139. &update,
  140. &creator.private_key.as_ref().unwrap(),
  141. &creator.actor_id,
  142. community.get_follower_inboxes(&conn)?,
  143. )?;
  144. Ok(())
  145. }
  146. fn send_delete(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
  147. let note = self.to_apub(&conn)?;
  148. let post = Post::read(&conn, self.post_id)?;
  149. let community = Community::read(&conn, post.community_id)?;
  150. let id = format!("{}/delete/{}", self.ap_id, uuid::Uuid::new_v4());
  151. let mut delete = Delete::default();
  152. populate_object_props(
  153. &mut delete.object_props,
  154. &community.get_followers_url(),
  155. &id,
  156. )?;
  157. delete
  158. .delete_props
  159. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  160. .set_object_base_box(note)?;
  161. // Insert the sent activity into the activity table
  162. let activity_form = activity::ActivityForm {
  163. user_id: creator.id,
  164. data: serde_json::to_value(&delete)?,
  165. local: true,
  166. updated: None,
  167. };
  168. activity::Activity::create(&conn, &activity_form)?;
  169. send_activity(
  170. &delete,
  171. &creator.private_key.as_ref().unwrap(),
  172. &creator.actor_id,
  173. community.get_follower_inboxes(&conn)?,
  174. )?;
  175. Ok(())
  176. }
  177. fn send_undo_delete(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
  178. let note = self.to_apub(&conn)?;
  179. let post = Post::read(&conn, self.post_id)?;
  180. let community = Community::read(&conn, post.community_id)?;
  181. // Generate a fake delete activity, with the correct object
  182. let id = format!("{}/delete/{}", self.ap_id, uuid::Uuid::new_v4());
  183. let mut delete = Delete::default();
  184. populate_object_props(
  185. &mut delete.object_props,
  186. &community.get_followers_url(),
  187. &id,
  188. )?;
  189. delete
  190. .delete_props
  191. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  192. .set_object_base_box(note)?;
  193. // TODO
  194. // Undo that fake activity
  195. let undo_id = format!("{}/undo/delete/{}", self.ap_id, uuid::Uuid::new_v4());
  196. let mut undo = Undo::default();
  197. populate_object_props(
  198. &mut undo.object_props,
  199. &community.get_followers_url(),
  200. &undo_id,
  201. )?;
  202. undo
  203. .undo_props
  204. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  205. .set_object_base_box(delete)?;
  206. // Insert the sent activity into the activity table
  207. let activity_form = activity::ActivityForm {
  208. user_id: creator.id,
  209. data: serde_json::to_value(&undo)?,
  210. local: true,
  211. updated: None,
  212. };
  213. activity::Activity::create(&conn, &activity_form)?;
  214. send_activity(
  215. &undo,
  216. &creator.private_key.as_ref().unwrap(),
  217. &creator.actor_id,
  218. community.get_follower_inboxes(&conn)?,
  219. )?;
  220. Ok(())
  221. }
  222. fn send_remove(&self, mod_: &User_, conn: &PgConnection) -> Result<(), Error> {
  223. let note = self.to_apub(&conn)?;
  224. let post = Post::read(&conn, self.post_id)?;
  225. let community = Community::read(&conn, post.community_id)?;
  226. let id = format!("{}/remove/{}", self.ap_id, uuid::Uuid::new_v4());
  227. let mut remove = Remove::default();
  228. populate_object_props(
  229. &mut remove.object_props,
  230. &community.get_followers_url(),
  231. &id,
  232. )?;
  233. remove
  234. .remove_props
  235. .set_actor_xsd_any_uri(mod_.actor_id.to_owned())?
  236. .set_object_base_box(note)?;
  237. // Insert the sent activity into the activity table
  238. let activity_form = activity::ActivityForm {
  239. user_id: mod_.id,
  240. data: serde_json::to_value(&remove)?,
  241. local: true,
  242. updated: None,
  243. };
  244. activity::Activity::create(&conn, &activity_form)?;
  245. send_activity(
  246. &remove,
  247. &mod_.private_key.as_ref().unwrap(),
  248. &mod_.actor_id,
  249. community.get_follower_inboxes(&conn)?,
  250. )?;
  251. Ok(())
  252. }
  253. fn send_undo_remove(&self, mod_: &User_, conn: &PgConnection) -> Result<(), Error> {
  254. let note = self.to_apub(&conn)?;
  255. let post = Post::read(&conn, self.post_id)?;
  256. let community = Community::read(&conn, post.community_id)?;
  257. // Generate a fake delete activity, with the correct object
  258. let id = format!("{}/remove/{}", self.ap_id, uuid::Uuid::new_v4());
  259. let mut remove = Remove::default();
  260. populate_object_props(
  261. &mut remove.object_props,
  262. &community.get_followers_url(),
  263. &id,
  264. )?;
  265. remove
  266. .remove_props
  267. .set_actor_xsd_any_uri(mod_.actor_id.to_owned())?
  268. .set_object_base_box(note)?;
  269. // Undo that fake activity
  270. let undo_id = format!("{}/undo/remove/{}", self.ap_id, uuid::Uuid::new_v4());
  271. let mut undo = Undo::default();
  272. populate_object_props(
  273. &mut undo.object_props,
  274. &community.get_followers_url(),
  275. &undo_id,
  276. )?;
  277. undo
  278. .undo_props
  279. .set_actor_xsd_any_uri(mod_.actor_id.to_owned())?
  280. .set_object_base_box(remove)?;
  281. // Insert the sent activity into the activity table
  282. let activity_form = activity::ActivityForm {
  283. user_id: mod_.id,
  284. data: serde_json::to_value(&undo)?,
  285. local: true,
  286. updated: None,
  287. };
  288. activity::Activity::create(&conn, &activity_form)?;
  289. send_activity(
  290. &undo,
  291. &mod_.private_key.as_ref().unwrap(),
  292. &mod_.actor_id,
  293. community.get_follower_inboxes(&conn)?,
  294. )?;
  295. Ok(())
  296. }
  297. }
  298. impl ApubLikeableType for Comment {
  299. fn send_like(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
  300. let note = self.to_apub(&conn)?;
  301. let post = Post::read(&conn, self.post_id)?;
  302. let community = Community::read(&conn, post.community_id)?;
  303. let id = format!("{}/like/{}", self.ap_id, uuid::Uuid::new_v4());
  304. let mut like = Like::new();
  305. populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
  306. like
  307. .like_props
  308. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  309. .set_object_base_box(note)?;
  310. // Insert the sent activity into the activity table
  311. let activity_form = activity::ActivityForm {
  312. user_id: creator.id,
  313. data: serde_json::to_value(&like)?,
  314. local: true,
  315. updated: None,
  316. };
  317. activity::Activity::create(&conn, &activity_form)?;
  318. send_activity(
  319. &like,
  320. &creator.private_key.as_ref().unwrap(),
  321. &creator.actor_id,
  322. community.get_follower_inboxes(&conn)?,
  323. )?;
  324. Ok(())
  325. }
  326. fn send_dislike(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
  327. let note = self.to_apub(&conn)?;
  328. let post = Post::read(&conn, self.post_id)?;
  329. let community = Community::read(&conn, post.community_id)?;
  330. let id = format!("{}/dislike/{}", self.ap_id, uuid::Uuid::new_v4());
  331. let mut dislike = Dislike::new();
  332. populate_object_props(
  333. &mut dislike.object_props,
  334. &community.get_followers_url(),
  335. &id,
  336. )?;
  337. dislike
  338. .dislike_props
  339. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  340. .set_object_base_box(note)?;
  341. // Insert the sent activity into the activity table
  342. let activity_form = activity::ActivityForm {
  343. user_id: creator.id,
  344. data: serde_json::to_value(&dislike)?,
  345. local: true,
  346. updated: None,
  347. };
  348. activity::Activity::create(&conn, &activity_form)?;
  349. send_activity(
  350. &dislike,
  351. &creator.private_key.as_ref().unwrap(),
  352. &creator.actor_id,
  353. community.get_follower_inboxes(&conn)?,
  354. )?;
  355. Ok(())
  356. }
  357. fn send_undo_like(&self, creator: &User_, conn: &PgConnection) -> Result<(), Error> {
  358. let note = self.to_apub(&conn)?;
  359. let post = Post::read(&conn, self.post_id)?;
  360. let community = Community::read(&conn, post.community_id)?;
  361. let id = format!("{}/dislike/{}", self.ap_id, uuid::Uuid::new_v4());
  362. let mut like = Like::new();
  363. populate_object_props(&mut like.object_props, &community.get_followers_url(), &id)?;
  364. like
  365. .like_props
  366. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  367. .set_object_base_box(note)?;
  368. // TODO
  369. // Undo that fake activity
  370. let undo_id = format!("{}/undo/like/{}", self.ap_id, uuid::Uuid::new_v4());
  371. let mut undo = Undo::default();
  372. populate_object_props(
  373. &mut undo.object_props,
  374. &community.get_followers_url(),
  375. &undo_id,
  376. )?;
  377. undo
  378. .undo_props
  379. .set_actor_xsd_any_uri(creator.actor_id.to_owned())?
  380. .set_object_base_box(like)?;
  381. // Insert the sent activity into the activity table
  382. let activity_form = activity::ActivityForm {
  383. user_id: creator.id,
  384. data: serde_json::to_value(&undo)?,
  385. local: true,
  386. updated: None,
  387. };
  388. activity::Activity::create(&conn, &activity_form)?;
  389. send_activity(
  390. &undo,
  391. &creator.private_key.as_ref().unwrap(),
  392. &creator.actor_id,
  393. community.get_follower_inboxes(&conn)?,
  394. )?;
  395. Ok(())
  396. }
  397. }