feat: Chat request implementation #14

Manually merged
awiteb merged 55 commits from awiteb/chat-request-and-response into master 2024-07-18 14:21:39 +02:00 AGit
3 changed files with 34 additions and 37 deletions
Showing only changes of commit 09f90b060f - Show all commits

View file

@ -35,13 +35,15 @@
/// [`Err`]: std::result::Result::Err /// [`Err`]: std::result::Result::Err
#[macro_export] #[macro_export]
macro_rules! try_ws { macro_rules! try_ws {
($result_expr:expr) => { (Some $result_expr:expr) => {
match $result_expr { match $result_expr {
Ok(val) => val, Ok(val) => val,
Err(err) => { Err(err) => {
log::error!("{err}"); log::error!("{err}");
return $crate::websocket::ServerEvent::<$crate::websocket::Unsigned>::from( return Some(
$crate::websocket::ServerEvent::<$crate::websocket::Unsigned>::from(
$crate::websocket::errors::WsError::from(err), $crate::websocket::errors::WsError::from(err),
),
); );
} }
} }

View file

@ -35,45 +35,42 @@ pub async fn handle_chat_request(
db: &DatabaseConnection, db: &DatabaseConnection,
from: Option<&UserModel>, from: Option<&UserModel>,
to_public_key: &PublicKey, to_public_key: &PublicKey,
) -> ServerEvent<Unsigned> { ) -> Option<ServerEvent<Unsigned>> {
let Some(from_user) = from else { let Some(from_user) = from else {
return WsError::RegistredUserEvent.into(); return Some(WsError::RegistredUserEvent.into());
}; };
let Some(to_user) = try_ws!(db.get_user_by_pubk(to_public_key).await) else { let Some(to_user) = try_ws!(Some db.get_user_by_pubk(to_public_key).await) else {
return WsError::UserNotFound.into(); return Some(WsError::UserNotFound.into());
}; };
if from_user.id == to_user.id { if from_user.id == to_user.id {
return WsError::CannotSendChatRequestToSelf.into(); return Some(WsError::CannotSendChatRequestToSelf.into());
} }
// FIXME: When change the entity public key to a PublicKey type, change this // FIXME: When change the entity public key to a PublicKey type, change this
let from_public_key = PublicKey::from_str(&from_user.public_key).expect("Is valid public key"); let from_public_key = PublicKey::from_str(&from_user.public_key).expect("Is valid public key");
if try_ws!(db.is_blacklisted(&to_user, &from_public_key).await) { if try_ws!(Some db.have_chat_request_to(from_user, to_public_key).await).is_some() {
return ServerEvent::message( return Some(WsError::AlreadySendChatRequest.into());
"You are unable to send a chat request because you are on the recipient's blacklist.",
);
}
if try_ws!(db.have_chat_request_to(from_user, to_public_key).await).is_some() {
return ServerEvent::message("You have already sent a chat request to this user.");
} }
awiteb marked this conversation as resolved
Review

Maybe would be better to move this to WsError easier to manage errors
there are also others below this

Maybe would be better to move this to `WsError` easier to manage errors there are also others below this
Review

Right, this should be an error, not a message. I don't know how is this happened

Right, this should be an error, not a message. I don't know how is this happened
Review

I'll remove Message event it is actually useless. I don't know why I thought it was good.

I'll remove `Message` event it is actually useless. I don't know why I thought it was good.
Review

I don't know why I thought it was good.

Well, I remembered when I added it, it was a pain to add a new error (before ws_error macro) so I thought it was good for simple messages.

> I don't know why I thought it was good. Well, I remembered when I added it, it was a pain to add a new error (before `ws_error` macro) so I thought it was good for simple messages.
try_ws!(db.add_to_whitelist(from_user, to_public_key).await); if try_ws!(Some db.is_blacklisted(&to_user, &from_public_key).await) {
return Some(WsError::RecipientBlacklist.into());
if try_ws!(db.is_whitelisted(&to_user, &from_public_key).await) {
return ServerEvent::message(
"You are already on the recipient's whitelist, so you can now chat with them.",
);
} }
try_ws!(db.save_out_chat_request(from_user, to_public_key).await); try_ws!(Some db.add_to_whitelist(from_user, to_public_key).await);
if try_ws!(Some db.is_whitelisted(&to_user, &from_public_key).await) {
return Some(WsError::AlreadyInRecipientWhitelist.into());
}
try_ws!(Some db.save_out_chat_request(from_user, to_public_key).await);
if let Some(conn_id) = ONLINE_USERS.is_online(to_public_key).await { if let Some(conn_id) = ONLINE_USERS.is_online(to_public_key).await {
ONLINE_USERS ONLINE_USERS
.send(&conn_id, ServerEvent::chat_request(&from_public_key)) .send(&conn_id, ServerEvent::chat_request(&from_public_key))
.await; .await;
} else { } else {
try_ws!(db.save_in_chat_request(&from_public_key, &to_user).await); try_ws!(Some db.save_in_chat_request(&from_public_key, &to_user).await);
} }
ServerEvent::message("Chat request sent successfully.") None
} }
pub async fn handle_chat_response( pub async fn handle_chat_response(
@ -81,28 +78,28 @@ pub async fn handle_chat_response(
recipient: Option<&UserModel>, recipient: Option<&UserModel>,
sender_public_key: &PublicKey, sender_public_key: &PublicKey,
accepted: bool, accepted: bool,
) -> ServerEvent<Unsigned> { ) -> Option<ServerEvent<Unsigned>> {
let Some(recipient_user) = recipient else { let Some(recipient_user) = recipient else {
return WsError::RegistredUserEvent.into(); return Some(WsError::RegistredUserEvent.into());
}; };
let Some(sender_user) = try_ws!(db.get_user_by_pubk(sender_public_key).await) else { let Some(sender_user) = try_ws!(Some db.get_user_by_pubk(sender_public_key).await) else {
return WsError::UserNotFound.into(); return Some(WsError::UserNotFound.into());
}; };
if recipient_user.id == sender_user.id { if recipient_user.id == sender_user.id {
return WsError::CannotRespondToOwnChatRequest.into(); return Some(WsError::CannotRespondToOwnChatRequest.into());
} }
// FIXME: When change the entity public key to a PublicKey type, change this // FIXME: When change the entity public key to a PublicKey type, change this
let recipient_public_key = let recipient_public_key =
PublicKey::from_str(&recipient_user.public_key).expect("Is valid public key"); PublicKey::from_str(&recipient_user.public_key).expect("Is valid public key");
if try_ws!( if try_ws!(Some
db.have_chat_request_to(&sender_user, &recipient_public_key) db.have_chat_request_to(&sender_user, &recipient_public_key)
.await .await
) )
.is_none() .is_none()
{ {
return WsError::NoChatRequestFromRecipient.into(); return Some(WsError::NoChatRequestFromRecipient.into());
} }
if let Some(conn_id) = ONLINE_USERS.is_online(sender_public_key).await { if let Some(conn_id) = ONLINE_USERS.is_online(sender_public_key).await {
@ -125,10 +122,10 @@ pub async fn handle_chat_response(
db.add_to_blacklist(recipient_user, sender_public_key).await db.add_to_blacklist(recipient_user, sender_public_key).await
}; };
try_ws!( try_ws!(Some
db.remove_out_chat_request(&sender_user, &recipient_public_key) db.remove_out_chat_request(&sender_user, &recipient_public_key)
.await .await
); );
ServerEvent::message("Chat request response sent successfully.") None
} }

View file

@ -216,11 +216,9 @@ async fn handle_events(
ONLINE_USERS.update_pong(conn_id).await; ONLINE_USERS.update_pong(conn_id).await;
None None
} }
ClientEventType::ChatRequest { to } => { ClientEventType::ChatRequest { to } => handlers::handle_chat_request(db, user, to).await,
Some(handlers::handle_chat_request(db, user, to).await)
}
ClientEventType::ChatRequestResponse { to, accepted } => { ClientEventType::ChatRequestResponse { to, accepted } => {
Some(handlers::handle_chat_response(db, user, to, *accepted).await) handlers::handle_chat_response(db, user, to, *accepted).await
} }
} }
} }