mirror of
https://codeberg.org/JasterV/chat-rooms-actix.git
synced 2026-04-26 18:10:04 +00:00
commands added & WsMessage data now is json
This commit is contained in:
parent
64c80bf54a
commit
adf255bd00
9 changed files with 119 additions and 30 deletions
57
Cargo.lock
generated
57
Cargo.lock
generated
|
|
@ -99,7 +99,7 @@ dependencies = [
|
||||||
"mime",
|
"mime",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project 1.0.5",
|
"pin-project 1.0.5",
|
||||||
"rand",
|
"rand 0.7.3",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|
@ -128,6 +128,7 @@ dependencies = [
|
||||||
"actix-web-actors",
|
"actix-web-actors",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"rand 0.8.3",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
|
@ -399,7 +400,7 @@ dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"mime",
|
"mime",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"rand",
|
"rand 0.7.3",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
|
|
@ -1269,9 +1270,21 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"getrandom 0.1.16",
|
"getrandom 0.1.16",
|
||||||
"libc",
|
"libc",
|
||||||
"rand_chacha",
|
"rand_chacha 0.2.2",
|
||||||
"rand_core",
|
"rand_core 0.5.1",
|
||||||
"rand_hc",
|
"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]]
|
[[package]]
|
||||||
|
|
@ -1281,7 +1294,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ppv-lite86",
|
"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]]
|
[[package]]
|
||||||
|
|
@ -1293,13 +1316,31 @@ dependencies = [
|
||||||
"getrandom 0.1.16",
|
"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]]
|
[[package]]
|
||||||
name = "rand_hc"
|
name = "rand_hc"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||||
dependencies = [
|
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]]
|
[[package]]
|
||||||
|
|
@ -1724,7 +1765,7 @@ dependencies = [
|
||||||
"idna",
|
"idna",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"rand",
|
"rand 0.7.3",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,5 @@ uuid = { version = "0.8", features = ["serde", "v4"] }
|
||||||
derive_more = "0.99.11"
|
derive_more = "0.99.11"
|
||||||
serde_json = "1.0.64"
|
serde_json = "1.0.64"
|
||||||
serde = "1.0.124"
|
serde = "1.0.124"
|
||||||
env_logger = "0.8.3"
|
env_logger = "0.8.3"
|
||||||
|
rand = "0.8.3"
|
||||||
|
|
@ -27,13 +27,16 @@ impl ChatServer {
|
||||||
.unwrap_or(false)
|
.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| {
|
self.rooms.get(room).map(|sessions| {
|
||||||
sessions.iter().for_each(|id| {
|
sessions.iter().for_each(|id| {
|
||||||
if id != skip_id {
|
if id != skip_id {
|
||||||
self.sessions
|
self.sessions.get(id).map(|addr| {
|
||||||
.get(id)
|
addr.do_send(Message {
|
||||||
.map(|addr| addr.do_send(Message(message.into())));
|
nickname: user.clone(),
|
||||||
|
msg: message.into(),
|
||||||
|
})
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -49,7 +52,7 @@ impl ChatServer {
|
||||||
}
|
}
|
||||||
// send message to other users
|
// send message to other users
|
||||||
for room in rooms {
|
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) {
|
if self.is_empty(&room) {
|
||||||
self.rooms.remove(&room);
|
self.rooms.remove(&room);
|
||||||
}
|
}
|
||||||
|
|
@ -95,8 +98,13 @@ impl Handler<ClientMessage> for ChatServer {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
|
|
||||||
fn handle(&mut self, msg: ClientMessage, _ctx: &mut Self::Context) -> Self::Result {
|
fn handle(&mut self, msg: ClientMessage, _ctx: &mut Self::Context) -> Self::Result {
|
||||||
let ClientMessage { session, room, msg } = msg;
|
let ClientMessage {
|
||||||
self.send_message(&room, &msg, &session);
|
session,
|
||||||
|
user,
|
||||||
|
room,
|
||||||
|
msg,
|
||||||
|
} = msg;
|
||||||
|
self.send_message(&room, &msg, &session, Some(user));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -129,7 +137,7 @@ impl Handler<JoinRoom> for ChatServer {
|
||||||
.rooms
|
.rooms
|
||||||
.get_mut(&room)
|
.get_mut(&room)
|
||||||
.map(|sessions| sessions.insert(session))
|
.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());
|
.ok_or("The room doesn't exists".into());
|
||||||
|
|
||||||
MessageResult(result)
|
MessageResult(result)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
actors::chat_server::ChatServer,
|
actors::chat_server::ChatServer,
|
||||||
constants::CLIENT_TIMEOUT,
|
constants::CLIENT_TIMEOUT,
|
||||||
models::{RoomId, SessionId},
|
models::{RoomId, SessionId, UserInfo},
|
||||||
};
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
constants::HEARTBEAT_INTERVAL,
|
constants::HEARTBEAT_INTERVAL,
|
||||||
|
|
@ -20,6 +20,7 @@ use actix::{
|
||||||
};
|
};
|
||||||
use actix::{Actor, Addr, AsyncContext};
|
use actix::{Actor, Addr, AsyncContext};
|
||||||
use actix_web_actors::ws::{self, WebsocketContext};
|
use actix_web_actors::ws::{self, WebsocketContext};
|
||||||
|
use serde_json::json;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
|
@ -28,6 +29,7 @@ pub struct WsChatSession {
|
||||||
pub room: Option<RoomId>,
|
pub room: Option<RoomId>,
|
||||||
pub addr: Addr<ChatServer>,
|
pub addr: Addr<ChatServer>,
|
||||||
pub hb: Instant,
|
pub hb: Instant,
|
||||||
|
pub user: UserInfo,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WsChatSession {
|
impl WsChatSession {
|
||||||
|
|
@ -36,6 +38,7 @@ impl WsChatSession {
|
||||||
id: Uuid::new_v4(),
|
id: Uuid::new_v4(),
|
||||||
room: None,
|
room: None,
|
||||||
hb: Instant::now(),
|
hb: Instant::now(),
|
||||||
|
user: UserInfo::default(),
|
||||||
addr,
|
addr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -92,7 +95,10 @@ impl Handler<Message> for WsChatSession {
|
||||||
type Result = ();
|
type Result = ();
|
||||||
|
|
||||||
fn handle(&mut self, msg: Message, ctx: &mut Self::Context) -> Self::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 = ();
|
type Result = ();
|
||||||
|
|
||||||
fn handle(&mut self, msg: WsMessage, ctx: &mut Self::Context) -> Self::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 {
|
match msg.ty {
|
||||||
MessageType::Create => self.create(ctx),
|
MessageType::Create => self.create(ctx),
|
||||||
MessageType::Join => match Uuid::from_str(&data) {
|
MessageType::Join => match Uuid::from_str(&data) {
|
||||||
Ok(uuid) => self.join(uuid, ctx),
|
Ok(uuid) => self.join(uuid, ctx),
|
||||||
Err(err) => ctx.text(WsMessage::err(err.to_string())),
|
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),
|
MessageType::Leave => self.leave(ctx),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +190,7 @@ impl WsChatSession {
|
||||||
act.room = Some(room_id.clone());
|
act.room = Some(room_id.clone());
|
||||||
ctx.text(WsMessage {
|
ctx.text(WsMessage {
|
||||||
ty: MessageType::Msg,
|
ty: MessageType::Msg,
|
||||||
data: Some("Joined!".into()),
|
data: json!("Joined!"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
Ok(res) => ctx.text(WsMessage::err(res.unwrap_err().to_string())),
|
Ok(res) => ctx.text(WsMessage::err(res.unwrap_err().to_string())),
|
||||||
|
|
@ -242,10 +248,12 @@ impl Handler<Command> for WsChatSession {
|
||||||
Command::Msg(msg) => {
|
Command::Msg(msg) => {
|
||||||
self.addr.do_send(ClientMessage {
|
self.addr.do_send(ClientMessage {
|
||||||
session: self.id.clone(),
|
session: self.id.clone(),
|
||||||
|
user: self.user.nickname.clone(),
|
||||||
room: room_id,
|
room: room_id,
|
||||||
msg,
|
msg,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Command::SetName(name) => self.user.nickname = name,
|
||||||
Command::GetRoomId => {
|
Command::GetRoomId => {
|
||||||
ctx.text(WsMessage::info(room_id.to_string()));
|
ctx.text(WsMessage::info(room_id.to_string()));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ use uuid::Uuid;
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub struct ClientMessage {
|
pub struct ClientMessage {
|
||||||
pub session: SessionId,
|
pub session: SessionId,
|
||||||
|
pub user: String,
|
||||||
pub room: RoomId,
|
pub room: RoomId,
|
||||||
pub msg: String,
|
pub msg: String,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ use std::str::FromStr;
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Msg(String),
|
Msg(String),
|
||||||
GetRoomId,
|
GetRoomId,
|
||||||
|
SetName(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Display, Error)]
|
#[derive(Debug, Display, Error)]
|
||||||
|
|
@ -22,11 +23,15 @@ impl FromStr for Command {
|
||||||
|
|
||||||
fn from_str(data: &str) -> Result<Self, Self::Err> {
|
fn from_str(data: &str) -> Result<Self, Self::Err> {
|
||||||
let words: Vec<&str> = data.trim().split_whitespace().collect();
|
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 {
|
if let Some((&command, words)) = opt {
|
||||||
return match word {
|
return match command {
|
||||||
"/roomId" => Ok(Command::GetRoomId),
|
"/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())),
|
_ => Ok(Command::Msg(data.into())),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
pub mod command;
|
pub mod command;
|
||||||
pub mod wsmessage;
|
pub mod wsmessage;
|
||||||
use actix::Message as ActixMessage;
|
use actix::Message as ActixMessage;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(ActixMessage)]
|
#[derive(Serialize, ActixMessage)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub struct Message(pub String);
|
pub struct Message {
|
||||||
|
pub nickname: Option<String>,
|
||||||
|
pub msg: String,
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,26 +1,27 @@
|
||||||
use actix::Message as ActixMessage;
|
use actix::Message as ActixMessage;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_json::{Value, json};
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, ActixMessage)]
|
#[derive(Serialize, Deserialize, ActixMessage)]
|
||||||
#[rtype(result = "()")]
|
#[rtype(result = "()")]
|
||||||
pub struct WsMessage {
|
pub struct WsMessage {
|
||||||
pub ty: MessageType,
|
pub ty: MessageType,
|
||||||
pub data: Option<String>,
|
pub data: Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WsMessage {
|
impl WsMessage {
|
||||||
pub fn err(msg: String) -> Self {
|
pub fn err(msg: String) -> Self {
|
||||||
WsMessage {
|
WsMessage {
|
||||||
ty: MessageType::Err,
|
ty: MessageType::Err,
|
||||||
data: Some(msg),
|
data: json!(msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn info(msg: String) -> Self {
|
pub fn info(msg: String) -> Self {
|
||||||
WsMessage {
|
WsMessage {
|
||||||
ty: MessageType::Info,
|
ty: MessageType::Info,
|
||||||
data: Some(msg),
|
data: json!(msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
use crate::actors::chat_server::ChatServer;
|
use crate::actors::chat_server::ChatServer;
|
||||||
use actix::Addr;
|
use actix::Addr;
|
||||||
|
use rand::distributions::Alphanumeric;
|
||||||
|
use rand::{thread_rng, Rng};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub type SessionId = Uuid;
|
pub type SessionId = Uuid;
|
||||||
|
|
@ -8,3 +10,21 @@ pub type RoomId = Uuid;
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
pub chat: Addr<ChatServer>,
|
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 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue