commands added & WsMessage data now is json

This commit is contained in:
Víctor Martínez 2021-03-22 00:58:39 +01:00
parent 64c80bf54a
commit adf255bd00
9 changed files with 119 additions and 30 deletions

57
Cargo.lock generated
View file

@ -99,7 +99,7 @@ dependencies = [
"mime",
"percent-encoding",
"pin-project 1.0.5",
"rand",
"rand 0.7.3",
"regex",
"serde",
"serde_json",
@ -128,6 +128,7 @@ dependencies = [
"actix-web-actors",
"derive_more",
"env_logger",
"rand 0.8.3",
"serde",
"serde_json",
"uuid",
@ -399,7 +400,7 @@ dependencies = [
"log",
"mime",
"percent-encoding",
"rand",
"rand 0.7.3",
"serde",
"serde_json",
"serde_urlencoded",
@ -1269,9 +1270,21 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
dependencies = [
"getrandom 0.1.16",
"libc",
"rand_chacha",
"rand_core",
"rand_hc",
"rand_chacha 0.2.2",
"rand_core 0.5.1",
"rand_hc 0.2.0",
]
[[package]]
name = "rand"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
dependencies = [
"libc",
"rand_chacha 0.3.0",
"rand_core 0.6.2",
"rand_hc 0.3.0",
]
[[package]]
@ -1281,7 +1294,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
dependencies = [
"ppv-lite86",
"rand_core",
"rand_core 0.5.1",
]
[[package]]
name = "rand_chacha"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
dependencies = [
"ppv-lite86",
"rand_core 0.6.2",
]
[[package]]
@ -1293,13 +1316,31 @@ dependencies = [
"getrandom 0.1.16",
]
[[package]]
name = "rand_core"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
dependencies = [
"getrandom 0.2.2",
]
[[package]]
name = "rand_hc"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
"rand_core",
"rand_core 0.5.1",
]
[[package]]
name = "rand_hc"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
dependencies = [
"rand_core 0.6.2",
]
[[package]]
@ -1724,7 +1765,7 @@ dependencies = [
"idna",
"lazy_static",
"log",
"rand",
"rand 0.7.3",
"smallvec",
"thiserror",
"tokio",

View file

@ -15,3 +15,4 @@ derive_more = "0.99.11"
serde_json = "1.0.64"
serde = "1.0.124"
env_logger = "0.8.3"
rand = "0.8.3"

View file

@ -27,13 +27,16 @@ impl ChatServer {
.unwrap_or(false)
}
pub fn send_message(&self, room: &Uuid, message: &str, skip_id: &Uuid) {
pub fn send_message(&self, room: &Uuid, message: &str, skip_id: &Uuid, user: Option<String>) {
self.rooms.get(room).map(|sessions| {
sessions.iter().for_each(|id| {
if id != skip_id {
self.sessions
.get(id)
.map(|addr| addr.do_send(Message(message.into())));
self.sessions.get(id).map(|addr| {
addr.do_send(Message {
nickname: user.clone(),
msg: message.into(),
})
});
}
});
});
@ -49,7 +52,7 @@ impl ChatServer {
}
// send message to other users
for room in rooms {
self.send_message(&room, "Someone disconnected", &session_id);
self.send_message(&room, "Someone disconnected", &session_id, None);
if self.is_empty(&room) {
self.rooms.remove(&room);
}
@ -95,8 +98,13 @@ impl Handler<ClientMessage> for ChatServer {
type Result = ();
fn handle(&mut self, msg: ClientMessage, _ctx: &mut Self::Context) -> Self::Result {
let ClientMessage { session, room, msg } = msg;
self.send_message(&room, &msg, &session);
let ClientMessage {
session,
user,
room,
msg,
} = msg;
self.send_message(&room, &msg, &session, Some(user));
}
}
@ -129,7 +137,7 @@ impl Handler<JoinRoom> for ChatServer {
.rooms
.get_mut(&room)
.map(|sessions| sessions.insert(session))
.map(|_| self.send_message(&room, "Someone connected", &session))
.map(|_| self.send_message(&room, "Someone connected", &session, None))
.ok_or("The room doesn't exists".into());
MessageResult(result)

View file

@ -1,7 +1,7 @@
use crate::{
actors::chat_server::ChatServer,
constants::CLIENT_TIMEOUT,
models::{RoomId, SessionId},
models::{RoomId, SessionId, UserInfo},
};
use crate::{
constants::HEARTBEAT_INTERVAL,
@ -20,6 +20,7 @@ use actix::{
};
use actix::{Actor, Addr, AsyncContext};
use actix_web_actors::ws::{self, WebsocketContext};
use serde_json::json;
use std::str::FromStr;
use uuid::Uuid;
@ -28,6 +29,7 @@ pub struct WsChatSession {
pub room: Option<RoomId>,
pub addr: Addr<ChatServer>,
pub hb: Instant,
pub user: UserInfo,
}
impl WsChatSession {
@ -36,6 +38,7 @@ impl WsChatSession {
id: Uuid::new_v4(),
room: None,
hb: Instant::now(),
user: UserInfo::default(),
addr,
}
}
@ -92,7 +95,10 @@ impl Handler<Message> for WsChatSession {
type Result = ();
fn handle(&mut self, msg: Message, ctx: &mut Self::Context) -> Self::Result {
ctx.text(msg.0);
ctx.text(WsMessage {
ty: MessageType::Msg,
data: json!(msg),
});
}
}
@ -132,14 +138,14 @@ impl Handler<WsMessage> for WsChatSession {
type Result = ();
fn handle(&mut self, msg: WsMessage, ctx: &mut Self::Context) -> Self::Result {
let data = msg.data.unwrap_or("".into());
let data = msg.data.as_str().unwrap();
match msg.ty {
MessageType::Create => self.create(ctx),
MessageType::Join => match Uuid::from_str(&data) {
Ok(uuid) => self.join(uuid, ctx),
Err(err) => ctx.text(WsMessage::err(err.to_string())),
},
MessageType::Msg => self.msg(data, ctx),
MessageType::Msg => self.msg(data.into(), ctx),
MessageType::Leave => self.leave(ctx),
_ => (),
}
@ -184,7 +190,7 @@ impl WsChatSession {
act.room = Some(room_id.clone());
ctx.text(WsMessage {
ty: MessageType::Msg,
data: Some("Joined!".into()),
data: json!("Joined!"),
})
}
Ok(res) => ctx.text(WsMessage::err(res.unwrap_err().to_string())),
@ -242,10 +248,12 @@ impl Handler<Command> for WsChatSession {
Command::Msg(msg) => {
self.addr.do_send(ClientMessage {
session: self.id.clone(),
user: self.user.nickname.clone(),
room: room_id,
msg,
});
}
Command::SetName(name) => self.user.nickname = name,
Command::GetRoomId => {
ctx.text(WsMessage::info(room_id.to_string()));
}

View file

@ -7,6 +7,7 @@ use uuid::Uuid;
#[rtype(result = "()")]
pub struct ClientMessage {
pub session: SessionId,
pub user: String,
pub room: RoomId,
pub msg: String,
}

View file

@ -8,6 +8,7 @@ use std::str::FromStr;
pub enum Command {
Msg(String),
GetRoomId,
SetName(String),
}
#[derive(Debug, Display, Error)]
@ -22,11 +23,15 @@ impl FromStr for Command {
fn from_str(data: &str) -> Result<Self, Self::Err> {
let words: Vec<&str> = data.trim().split_whitespace().collect();
let first_word = words.first();
let opt = words.split_first();
if let Some(&word) = first_word {
return match word {
if let Some((&command, words)) = opt {
return match command {
"/roomId" => Ok(Command::GetRoomId),
"/setName" if words.len() > 0 => Ok(Command::SetName(words[0].into())),
"/setName" => Err(CommandError {
msg: "Invalid empty name",
}),
_ => Ok(Command::Msg(data.into())),
};
}

View file

@ -1,7 +1,11 @@
pub mod command;
pub mod wsmessage;
use actix::Message as ActixMessage;
use serde::Serialize;
#[derive(ActixMessage)]
#[derive(Serialize, ActixMessage)]
#[rtype(result = "()")]
pub struct Message(pub String);
pub struct Message {
pub nickname: Option<String>,
pub msg: String,
}

View file

@ -1,26 +1,27 @@
use actix::Message as ActixMessage;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
use std::convert::Into;
#[derive(Serialize, Deserialize, ActixMessage)]
#[rtype(result = "()")]
pub struct WsMessage {
pub ty: MessageType,
pub data: Option<String>,
pub data: Value,
}
impl WsMessage {
pub fn err(msg: String) -> Self {
WsMessage {
ty: MessageType::Err,
data: Some(msg),
data: json!(msg),
}
}
pub fn info(msg: String) -> Self {
WsMessage {
ty: MessageType::Info,
data: Some(msg),
data: json!(msg),
}
}
}

View file

@ -1,5 +1,7 @@
use crate::actors::chat_server::ChatServer;
use actix::Addr;
use rand::distributions::Alphanumeric;
use rand::{thread_rng, Rng};
use uuid::Uuid;
pub type SessionId = Uuid;
@ -8,3 +10,21 @@ pub type RoomId = Uuid;
pub struct AppState {
pub chat: Addr<ChatServer>,
}
pub struct UserInfo {
pub nickname: String,
}
impl Default for UserInfo {
fn default() -> Self {
let rand_string: String = thread_rng()
.sample_iter(&Alphanumeric)
.take(15)
.map(char::from)
.collect();
let nickname = format!("User-{}", rand_string);
UserInfo { nickname }
}
}