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",
|
||||
"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",
|
||||
|
|
|
|||
|
|
@ -14,4 +14,5 @@ uuid = { version = "0.8", features = ["serde", "v4"] }
|
|||
derive_more = "0.99.11"
|
||||
serde_json = "1.0.64"
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ use uuid::Uuid;
|
|||
#[rtype(result = "()")]
|
||||
pub struct ClientMessage {
|
||||
pub session: SessionId,
|
||||
pub user: String,
|
||||
pub room: RoomId,
|
||||
pub msg: String,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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())),
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue