From: eiknat <eiknat@protonmail.com>
Date: Tue, 27 Oct 2020 00:25:18 +0000 (-0400)
Subject: add mod room websocket impl
X-Git-Url: http://these/git/%22https:/image.com/static/git-favicon.png?a=commitdiff_plain;h=30d784c27c1cc7517a5c8fd3ed537475aa731ffa;p=lemmy.git

add mod room websocket impl
---

diff --git a/lemmy_api/src/comment.rs b/lemmy_api/src/comment.rs
index e9ed0a44..2b0ee054 100644
--- a/lemmy_api/src/comment.rs
+++ b/lemmy_api/src/comment.rs
@@ -34,6 +34,7 @@ use lemmy_utils::{
 };
 use lemmy_websocket::{messages::{SendComment, SendUserRoomMessage}, LemmyContext, UserOperation};
 use std::str::FromStr;
+use lemmy_websocket::messages::SendModRoomMessage;
 
 #[async_trait::async_trait(?Send)]
 impl Perform for CreateComment {
@@ -693,7 +694,7 @@ impl Perform for CreateCommentReport {
   async fn perform(
     &self,
     context: &Data<LemmyContext>,
-    _websocket_id: Option<ConnectionId>,
+    websocket_id: Option<ConnectionId>,
   ) -> Result<CreateCommentReportResponse, LemmyError> {
     let data: &CreateCommentReport = &self;
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
@@ -722,24 +723,28 @@ impl Perform for CreateCommentReport {
       reason: data.reason.to_owned(),
     };
 
-    let _report = match blocking(context.pool(), move |conn| {
+    let report = match blocking(context.pool(), move |conn| {
       CommentReport::report(conn, &report_form)
     }).await? {
       Ok(report) => report,
       Err(_e) => return Err(APIError::err("couldnt_create_report").into())
     };
 
-    // to build on this, the user should get a success response, however
-    // mods should get a different response with more details
     let res = CreateCommentReportResponse { success: true };
 
-    // TODO this needs to use a SendModRoomMessage
-    // context.chat_server().do_send(SendUserRoomMessage {
-    //   op: UserOperation::CreateReport,
-    //   response: res.clone(),
-    //   recipient_id: user.id,
-    //   websocket_id,
-    // });
+    context.chat_server().do_send(SendUserRoomMessage {
+      op: UserOperation::CreateCommentReport,
+      response: res.clone(),
+      recipient_id: user.id,
+      websocket_id,
+    });
+
+    context.chat_server().do_send(SendModRoomMessage {
+      op: UserOperation::CreateCommentReport,
+      response: report,
+      community_id: comment.community_id,
+      websocket_id,
+    });
 
     Ok(res)
   }
@@ -752,7 +757,7 @@ impl Perform for ResolveCommentReport {
   async fn perform(
     &self,
     context: &Data<LemmyContext>,
-    _websocket_id: Option<ConnectionId>,
+    websocket_id: Option<ConnectionId>,
   ) -> Result<ResolveCommentReportResponse, LemmyError> {
     let data: &ResolveCommentReport = &self;
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
@@ -784,13 +789,12 @@ impl Perform for ResolveCommentReport {
       resolved,
     };
 
-    // TODO this needs to use a SendModRoomMessage
-    // context.chat_server().do_send(SendUserRoomMessage {
-    //   op: UserOperation::ResolveCommentReport,
-    //   response: res.clone(),
-    //   recipient_id: user.id,
-    //   websocket_id,
-    // });
+    context.chat_server().do_send(SendModRoomMessage {
+      op: UserOperation::ResolveCommentReport,
+      response: res.clone(),
+      community_id: report.community_id,
+      websocket_id,
+    });
 
     Ok(res)
   }
diff --git a/lemmy_api/src/community.rs b/lemmy_api/src/community.rs
index a9e130b9..ae19c5f8 100644
--- a/lemmy_api/src/community.rs
+++ b/lemmy_api/src/community.rs
@@ -41,6 +41,7 @@ use lemmy_websocket::{
   UserOperation,
 };
 use std::str::FromStr;
+use lemmy_websocket::messages::JoinModRoom;
 
 #[async_trait::async_trait(?Send)]
 impl Perform for GetCommunity {
@@ -883,3 +884,26 @@ impl Perform for CommunityJoin {
     Ok(CommunityJoinResponse { joined: true })
   }
 }
+
+// is this the right place for this?
+#[async_trait::async_trait(?Send)]
+impl Perform for ModJoin {
+  type Response = ModJoinResponse;
+
+  async fn perform(
+    &self,
+    context: &Data<LemmyContext>,
+    websocket_id: Option<ConnectionId>,
+  ) -> Result<ModJoinResponse, LemmyError> {
+    let data: &ModJoin = &self;
+
+    if let Some(ws_id) = websocket_id {
+      context.chat_server().do_send(JoinModRoom {
+        community_id: data.community_id,
+        id: ws_id,
+      });
+    }
+
+    Ok(ModJoinResponse { joined: true })
+  }
+}
diff --git a/lemmy_api/src/lib.rs b/lemmy_api/src/lib.rs
index 38cf8043..96f2b061 100644
--- a/lemmy_api/src/lib.rs
+++ b/lemmy_api/src/lib.rs
@@ -195,6 +195,9 @@ pub async fn match_websocket_operation(
     UserOperation::CommunityJoin => {
       do_websocket_operation::<CommunityJoin>(context, id, op, data).await
     }
+    UserOperation::ModJoin => {
+      do_websocket_operation::<ModJoin>(context, id, op, data).await
+    }
     UserOperation::SaveUserSettings => {
       do_websocket_operation::<SaveUserSettings>(context, id, op, data).await
     }
diff --git a/lemmy_api/src/post.rs b/lemmy_api/src/post.rs
index 0bf76b4d..0abb879c 100644
--- a/lemmy_api/src/post.rs
+++ b/lemmy_api/src/post.rs
@@ -35,7 +35,13 @@ use lemmy_utils::{
   LemmyError,
 };
 use lemmy_websocket::{
-  messages::{GetPostUsersOnline, JoinPostRoom, SendPost, SendUserRoomMessage},
+  messages::{
+    GetPostUsersOnline,
+    JoinPostRoom,
+    SendModRoomMessage,
+    SendPost,
+    SendUserRoomMessage
+  },
   LemmyContext,
   UserOperation,
 };
@@ -752,7 +758,7 @@ impl Perform for CreatePostReport {
   async fn perform(
     &self,
     context: &Data<LemmyContext>,
-    _websocket_id: Option<ConnectionId>,
+    websocket_id: Option<ConnectionId>,
   ) -> Result<CreatePostReportResponse, LemmyError> {
     let data: &CreatePostReport = &self;
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
@@ -783,24 +789,28 @@ impl Perform for CreatePostReport {
       reason: data.reason.to_owned(),
     };
 
-    let _report = match blocking(context.pool(), move |conn| {
+    let report = match blocking(context.pool(), move |conn| {
       PostReport::report(conn, &report_form)
     }).await? {
       Ok(report) => report,
       Err(_e) => return Err(APIError::err("couldnt_create_report").into())
     };
 
-    // to build on this, the user should get a success response, however
-    // mods should get a different response with more details
     let res = CreatePostReportResponse { success: true };
 
-    // TODO this needs to use a SendModRoomMessage
-    // context.chat_server().do_send(SendUserRoomMessage {
-    //   op: UserOperation::CreateReport,
-    //   response: res.clone(),
-    //   recipient_id: user.id,
-    //   websocket_id,
-    // });
+    context.chat_server().do_send(SendUserRoomMessage {
+      op: UserOperation::CreatePostReport,
+      response: res.clone(),
+      recipient_id: user.id,
+      websocket_id,
+    });
+
+    context.chat_server().do_send(SendModRoomMessage {
+      op: UserOperation::CreatePostReport,
+      response: report,
+      community_id: post.community_id,
+      websocket_id,
+    });
 
     Ok(res)
   }
@@ -813,7 +823,7 @@ impl Perform for ResolvePostReport {
   async fn perform(
     &self,
     context: &Data<LemmyContext>,
-    _websocket_id: Option<ConnectionId>,
+    websocket_id: Option<ConnectionId>,
   ) -> Result<ResolvePostReportResponse, LemmyError> {
     let data: &ResolvePostReport = &self;
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
@@ -844,13 +854,12 @@ impl Perform for ResolvePostReport {
       return Err(APIError::err("couldnt_resolve_report").into())
     };
 
-    // TODO this needs to use a SendModRoomMessage
-    // context.chat_server().do_send(SendUserRoomMessage {
-    //   op: UserOperation::ResolvePostReport,
-    //   response: res.clone(),
-    //   recipient_id: user.id,
-    //   websocket_id,
-    // });
+    context.chat_server().do_send(SendModRoomMessage {
+      op: UserOperation::ResolvePostReport,
+      response: res.clone(),
+      community_id: report.community_id,
+      websocket_id,
+    });
 
     Ok(res)
   }
diff --git a/lemmy_db/src/comment_report.rs b/lemmy_db/src/comment_report.rs
index a2b4e1d3..a5ac701c 100644
--- a/lemmy_db/src/comment_report.rs
+++ b/lemmy_db/src/comment_report.rs
@@ -23,7 +23,7 @@ table! {
     }
 }
 
-#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
+#[derive(Identifiable, Queryable, Associations, PartialEq, Debug, Serialize)]
 #[belongs_to(Comment)]
 #[table_name = "comment_report"]
 pub struct CommentReport {
diff --git a/lemmy_structs/src/community.rs b/lemmy_structs/src/community.rs
index 6c543eac..3535c05a 100644
--- a/lemmy_structs/src/community.rs
+++ b/lemmy_structs/src/community.rs
@@ -139,3 +139,13 @@ pub struct CommunityJoin {
 pub struct CommunityJoinResponse {
   pub joined: bool,
 }
+
+#[derive(Deserialize, Debug)]
+pub struct ModJoin {
+  pub community_id: i32,
+}
+
+#[derive(Serialize, Clone)]
+pub struct ModJoinResponse {
+  pub joined: bool,
+}
diff --git a/lemmy_websocket/src/chat_server.rs b/lemmy_websocket/src/chat_server.rs
index 8346a32f..0a524e3d 100644
--- a/lemmy_websocket/src/chat_server.rs
+++ b/lemmy_websocket/src/chat_server.rs
@@ -47,6 +47,8 @@ pub struct ChatServer {
   /// A map from community to set of connectionIDs
   pub community_rooms: HashMap<CommunityId, HashSet<ConnectionId>>,
 
+  pub mod_rooms: HashMap<CommunityId, HashSet<ConnectionId>>,
+
   /// A map from user id to its connection ID for joined users. Remember a user can have multiple
   /// sessions (IE clients)
   pub(super) user_rooms: HashMap<UserId, HashSet<ConnectionId>>,
@@ -90,6 +92,7 @@ impl ChatServer {
       sessions: HashMap::new(),
       post_rooms: HashMap::new(),
       community_rooms: HashMap::new(),
+      mod_rooms: HashMap::new(),
       user_rooms: HashMap::new(),
       rng: rand::thread_rng(),
       pool,
@@ -130,6 +133,29 @@ impl ChatServer {
     Ok(())
   }
 
+  pub fn join_mod_room(
+    &mut self,
+    community_id: CommunityId,
+    id: ConnectionId,
+  ) -> Result<(), LemmyError> {
+    // remove session from all rooms
+    for sessions in self.mod_rooms.values_mut() {
+      sessions.remove(&id);
+    }
+
+    // If the room doesn't exist yet
+    if self.mod_rooms.get_mut(&community_id).is_none() {
+      self.mod_rooms.insert(community_id, HashSet::new());
+    }
+
+    self
+      .mod_rooms
+      .get_mut(&community_id)
+      .context(location_info!())?
+      .insert(id);
+    Ok(())
+  }
+
   pub fn join_post_room(&mut self, post_id: PostId, id: ConnectionId) -> Result<(), LemmyError> {
     // remove session from all rooms
     for sessions in self.post_rooms.values_mut() {
@@ -227,6 +253,30 @@ impl ChatServer {
     Ok(())
   }
 
+  pub fn send_mod_room_message<Response>(
+    &self,
+    op: &UserOperation,
+    response: &Response,
+    community_id: CommunityId,
+    websocket_id: Option<ConnectionId>,
+  ) -> Result<(), LemmyError>
+    where
+      Response: Serialize,
+  {
+    let res_str = &serialize_websocket_message(op, response)?;
+    if let Some(sessions) = self.mod_rooms.get(&community_id) {
+      for id in sessions {
+        if let Some(my_id) = websocket_id {
+          if *id == my_id {
+            continue;
+          }
+        }
+        self.sendit(res_str, *id);
+      }
+    }
+    Ok(())
+  }
+
   pub fn send_all_message<Response>(
     &self,
     op: &UserOperation,
diff --git a/lemmy_websocket/src/handlers.rs b/lemmy_websocket/src/handlers.rs
index 258098d6..0b5703ab 100644
--- a/lemmy_websocket/src/handlers.rs
+++ b/lemmy_websocket/src/handlers.rs
@@ -120,6 +120,19 @@ where
   }
 }
 
+impl<Response> Handler<SendModRoomMessage<Response>> for ChatServer
+  where
+    Response: Serialize,
+{
+  type Result = ();
+
+  fn handle(&mut self, msg: SendModRoomMessage<Response>, _: &mut Context<Self>) {
+    self
+      .send_mod_room_message(&msg.op, &msg.response, msg.community_id, msg.websocket_id)
+      .ok();
+  }
+}
+
 impl Handler<SendPost> for ChatServer {
   type Result = ();
 
@@ -154,6 +167,14 @@ impl Handler<JoinCommunityRoom> for ChatServer {
   }
 }
 
+impl Handler<JoinModRoom> for ChatServer {
+  type Result = ();
+
+  fn handle(&mut self, msg: JoinModRoom, _: &mut Context<Self>) {
+    self.join_mod_room(msg.community_id, msg.id).ok();
+  }
+}
+
 impl Handler<JoinPostRoom> for ChatServer {
   type Result = ();
 
diff --git a/lemmy_websocket/src/lib.rs b/lemmy_websocket/src/lib.rs
index 7673510c..d789efdd 100644
--- a/lemmy_websocket/src/lib.rs
+++ b/lemmy_websocket/src/lib.rs
@@ -148,4 +148,5 @@ pub enum UserOperation {
   SaveSiteConfig,
   PostJoin,
   CommunityJoin,
+  ModJoin,
 }
diff --git a/lemmy_websocket/src/messages.rs b/lemmy_websocket/src/messages.rs
index d9f8320a..c678a96e 100644
--- a/lemmy_websocket/src/messages.rs
+++ b/lemmy_websocket/src/messages.rs
@@ -63,6 +63,15 @@ pub struct SendCommunityRoomMessage<Response> {
   pub websocket_id: Option<ConnectionId>,
 }
 
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct SendModRoomMessage<Response> {
+  pub op: UserOperation,
+  pub response: Response,
+  pub community_id: CommunityId,
+  pub websocket_id: Option<ConnectionId>,
+}
+
 #[derive(Message)]
 #[rtype(result = "()")]
 pub struct SendPost {
@@ -93,6 +102,13 @@ pub struct JoinCommunityRoom {
   pub id: ConnectionId,
 }
 
+#[derive(Message)]
+#[rtype(result = "()")]
+pub struct JoinModRoom {
+  pub community_id: CommunityId,
+  pub id: ConnectionId,
+}
+
 #[derive(Message)]
 #[rtype(result = "()")]
 pub struct JoinPostRoom {
diff --git a/src/routes/api.rs b/src/routes/api.rs
index e6d6b31a..7b95b4ee 100644
--- a/src/routes/api.rs
+++ b/src/routes/api.rs
@@ -57,7 +57,8 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
           .route("/transfer", web::post().to(route_post::<TransferCommunity>))
           .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
           .route("/mod", web::post().to(route_post::<AddModToCommunity>))
-          .route("/join", web::post().to(route_post::<CommunityJoin>)),
+          .route("/join", web::post().to(route_post::<CommunityJoin>))
+          .route("/mod/join", web::post().to(route_post::<ModJoin>)),
       )
       // Post
       .service(