add mod room websocket impl

pull/1197/head
eiknat 2020-10-26 20:25:18 -04:00 committed by eiknat
parent 070efe72af
commit 30d784c27c
11 changed files with 180 additions and 41 deletions

View File

@ -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)
}

View File

@ -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 })
}
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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 {

View File

@ -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,
}

View File

@ -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,

View File

@ -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 = ();

View File

@ -148,4 +148,5 @@ pub enum UserOperation {
SaveSiteConfig,
PostJoin,
CommunityJoin,
ModJoin,
}

View File

@ -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 {

View File

@ -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(