feat(lib): send and receive private messages
Wire private messaging through the client: - MessageFactory::build_message_user (code 22) and build_message_acked (code 23); - the incoming MessageUser handler now acknowledges freshly delivered messages and forwards them to the client instead of only logging them; - ClientContext buffers received UserMessages; - Client::send_private_message and Client::take_private_messages expose the feature, and UserMessage (with accessors) is re-exported from the crate. Verified end to end against soulfind: a_private_message_is_delivered_between_users logs in two clients and asserts one receives the other's message.
This commit is contained in:
@@ -63,6 +63,23 @@ impl MessageFactory {
|
||||
.write_string(query)
|
||||
.clone()
|
||||
}
|
||||
/// Build a private message (server code 22) to send to another user.
|
||||
#[must_use]
|
||||
pub fn build_message_user(username: &str, message: &str) -> Message {
|
||||
Message::new()
|
||||
.write_int32(22)
|
||||
.write_string(username)
|
||||
.write_string(message)
|
||||
.clone()
|
||||
}
|
||||
|
||||
/// Acknowledge a received private message (server code 23) so the server
|
||||
/// stops re-delivering it.
|
||||
#[must_use]
|
||||
pub fn build_message_acked(id: u32) -> Message {
|
||||
Message::new().write_int32(23).write_int32(id).clone()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn build_set_status_message(status_code: u32) -> Message {
|
||||
Message::new()
|
||||
@@ -167,6 +184,25 @@ fn test_build_login_message() {
|
||||
assert_eq!(expect, message.get_data());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_message_user() {
|
||||
let message = MessageFactory::build_message_user("bob", "hi");
|
||||
let expect: Vec<u8> = [
|
||||
22, 0, 0, 0, // code
|
||||
3, 0, 0, 0, 98, 111, 98, // username "bob"
|
||||
2, 0, 0, 0, 104, 105, // message "hi"
|
||||
]
|
||||
.to_vec();
|
||||
assert_eq!(expect, message.get_data());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_message_acked() {
|
||||
let message = MessageFactory::build_message_acked(7);
|
||||
let expect: Vec<u8> = [23, 0, 0, 0, 7, 0, 0, 0].to_vec();
|
||||
assert_eq!(expect, message.get_data());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_build_file_search_message() {
|
||||
let message = MessageFactory::build_file_search_message(12, "trance wax");
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::actor::server_actor::{ServerMessage, UserMessage};
|
||||
use crate::info;
|
||||
use crate::message::server::MessageFactory;
|
||||
use crate::message::{Message, MessageHandler};
|
||||
|
||||
use std::sync::mpsc::Sender;
|
||||
@@ -11,7 +12,7 @@ impl MessageHandler<ServerMessage> for MessageUser {
|
||||
22
|
||||
}
|
||||
|
||||
fn handle(&self, message: &mut Message, _sender: Sender<ServerMessage>) {
|
||||
fn handle(&self, message: &mut Message, sender: Sender<ServerMessage>) {
|
||||
let id = message.read_int32();
|
||||
let timestamp = message.read_int32();
|
||||
let username = message.read_string();
|
||||
@@ -27,5 +28,17 @@ impl MessageHandler<ServerMessage> for MessageUser {
|
||||
|
||||
info!("[MessageUser] User message received:{:?}", user_message);
|
||||
user_message.print();
|
||||
|
||||
// Acknowledge freshly delivered messages so the server does not keep
|
||||
// re-sending them on every reconnect.
|
||||
if new_message {
|
||||
let _ = sender.send(ServerMessage::SendMessage(
|
||||
MessageFactory::build_message_acked(id),
|
||||
));
|
||||
}
|
||||
|
||||
// Surface the message to the client so it can be read via the API.
|
||||
let _ =
|
||||
sender.send(ServerMessage::PrivateMessageReceived(user_message));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user