diff options
Diffstat (limited to 'filamento/src/lib.rs')
-rw-r--r-- | filamento/src/lib.rs | 459 |
1 files changed, 384 insertions, 75 deletions
diff --git a/filamento/src/lib.rs b/filamento/src/lib.rs index c44edca..d3033b7 100644 --- a/filamento/src/lib.rs +++ b/filamento/src/lib.rs @@ -11,11 +11,12 @@ use chrono::Utc; use db::Db; use disco::{Info, Items}; use error::{ - ConnectionJobError, DatabaseError, DiscoError, Error, IqError, MessageRecvError, NickError, - PresenceError, PublishError, RosterError, StatusError, SubscribeError, + AvatarPublishError, ConnectionJobError, DatabaseError, DiscoError, Error, IqError, + MessageRecvError, NickError, PEPError, PresenceError, RosterError, StatusError, SubscribeError, }; +use files::FileStore; use futures::FutureExt; -use jid::JID; +use jid::{BareJID, JID}; use lampada::{ Connected, CoreClient, CoreClientCommand, Logic, SupervisorSender, WriteMessage, error::{ActorError, CommandError, ConnectionError, ReadError, WriteError}, @@ -31,24 +32,30 @@ use tokio::{ sync::{Mutex, mpsc, oneshot}, time::timeout, }; +#[cfg(target_arch = "wasm32")] +use tokio_with_wasm::alias as tokio; use tracing::{debug, info}; use user::User; use uuid::Uuid; +pub mod avatar; pub mod caps; pub mod chat; pub mod db; pub mod disco; pub mod error; +pub mod files; mod logic; pub mod pep; pub mod presence; pub mod roster; pub mod user; -pub enum Command { +pub enum Command<Fs: FileStore> { /// get the roster. if offline, retreive cached version from database. should be stored in application memory GetRoster(oneshot::Sender<Result<Vec<Contact>, RosterError>>), + /// get the roster. if offline, retreive cached version from database. should be stored in application memory. includes user associated with each contact + GetRosterWithUsers(oneshot::Sender<Result<Vec<(Contact, User)>, RosterError>>), /// get all chats. chat will include 10 messages in their message Vec (enough for chat previews) // TODO: paging and filtering GetChats(oneshot::Sender<Result<Vec<Chat>, DatabaseError>>), @@ -56,37 +63,60 @@ pub enum Command { GetChatsOrdered(oneshot::Sender<Result<Vec<Chat>, DatabaseError>>), // TODO: paging and filtering GetChatsOrderedWithLatestMessages(oneshot::Sender<Result<Vec<(Chat, Message)>, DatabaseError>>), + // TODO: paging and filtering, nullabillity for latest message + GetChatsOrderedWithLatestMessagesAndUsers( + oneshot::Sender<Result<Vec<((Chat, User), (Message, User))>, DatabaseError>>, + ), /// get a specific chat by jid - GetChat(JID, oneshot::Sender<Result<Chat, DatabaseError>>), + GetChat(BareJID, oneshot::Sender<Result<Chat, DatabaseError>>), + /// get a specific chat and user by jid + GetChatAndUser( + BareJID, + oneshot::Sender<Result<(Chat, User), DatabaseError>>, + ), + /// get message history for chat (does appropriate mam things) + GetMessage(Uuid, oneshot::Sender<Result<Message, DatabaseError>>), + // TODO: paging and filtering + GetMessages( + BareJID, + oneshot::Sender<Result<Vec<Message>, DatabaseError>>, + ), /// get message history for chat (does appropriate mam things) // TODO: paging and filtering - GetMessages(JID, oneshot::Sender<Result<Vec<Message>, DatabaseError>>), + GetMessagesWithUsers( + BareJID, + oneshot::Sender<Result<Vec<(Message, User)>, DatabaseError>>, + ), /// delete a chat from your chat history, along with all the corresponding messages - DeleteChat(JID, oneshot::Sender<Result<(), DatabaseError>>), + DeleteChat(BareJID, oneshot::Sender<Result<(), DatabaseError>>), /// delete a message from your chat history DeleteMessage(Uuid, oneshot::Sender<Result<(), DatabaseError>>), /// get a user from your users database - GetUser(JID, oneshot::Sender<Result<User, DatabaseError>>), + GetUser(BareJID, oneshot::Sender<Result<User, DatabaseError>>), /// add a contact to your roster, with a status of none, no subscriptions. - AddContact(JID, oneshot::Sender<Result<(), RosterError>>), + AddContact(BareJID, oneshot::Sender<Result<(), RosterError>>), /// send a friend request i.e. a subscription request with a subscription pre-approval. if not already added to roster server adds to roster. - BuddyRequest(JID, oneshot::Sender<Result<(), SubscribeError>>), + BuddyRequest(BareJID, oneshot::Sender<Result<(), SubscribeError>>), /// send a subscription request, without pre-approval. if not already added to roster server adds to roster. - SubscriptionRequest(JID, oneshot::Sender<Result<(), SubscribeError>>), + SubscriptionRequest(BareJID, oneshot::Sender<Result<(), SubscribeError>>), /// accept a friend request by accepting a pending subscription and sending a subscription request back. if not already added to roster adds to roster. - AcceptBuddyRequest(JID, oneshot::Sender<Result<(), SubscribeError>>), + AcceptBuddyRequest(BareJID, oneshot::Sender<Result<(), SubscribeError>>), /// accept a pending subscription and doesn't send a subscription request back. if not already added to roster adds to roster. - AcceptSubscriptionRequest(JID, oneshot::Sender<Result<(), SubscribeError>>), + AcceptSubscriptionRequest(BareJID, oneshot::Sender<Result<(), SubscribeError>>), /// unsubscribe to a contact, but don't remove their subscription. - UnsubscribeFromContact(JID, oneshot::Sender<Result<(), WriteError>>), + UnsubscribeFromContact(BareJID, oneshot::Sender<Result<(), WriteError>>), /// stop a contact from being subscribed, but stay subscribed to the contact. - UnsubscribeContact(JID, oneshot::Sender<Result<(), WriteError>>), + UnsubscribeContact(BareJID, oneshot::Sender<Result<(), WriteError>>), /// remove subscriptions to and from contact, but keep in roster. - UnfriendContact(JID, oneshot::Sender<Result<(), WriteError>>), + UnfriendContact(BareJID, oneshot::Sender<Result<(), WriteError>>), /// remove a contact from the contact list. will remove subscriptions if not already done then delete contact from roster. - DeleteContact(JID, oneshot::Sender<Result<(), RosterError>>), + DeleteContact(BareJID, oneshot::Sender<Result<(), RosterError>>), /// update contact. contact details will be overwritten with the contents of the contactupdate struct. - UpdateContact(JID, ContactUpdate, oneshot::Sender<Result<(), RosterError>>), + UpdateContact( + BareJID, + ContactUpdate, + oneshot::Sender<Result<(), RosterError>>, + ), /// set online status. if disconnected, will be cached so when client connects, will be sent as the initial presence. SetStatus(Online, oneshot::Sender<Result<(), StatusError>>), /// send presence stanza @@ -100,7 +130,7 @@ pub enum Command { // TODO: should probably make it so people can add non-contact auto presence sharing in the client (most likely through setting an internal setting) /// send a message to a jid (any kind of jid that can receive a message, e.g. a user or a /// chatroom). if disconnected, will be cached so when client connects, message will be sent. - SendMessage(JID, Body), + SendMessage(BareJID, Body), // TODO: resend failed messages // ResendMessage(Uuid), /// disco info query @@ -115,28 +145,43 @@ pub enum Command { Option<String>, oneshot::Sender<Result<disco::Items, DiscoError>>, ), - /// publish item to a pep node, specified or default according to item. - Publish { + /// publish item to a pep node specified. + PublishPEPItem { item: pep::Item, node: String, - sender: oneshot::Sender<Result<(), PublishError>>, + sender: oneshot::Sender<Result<(), PEPError>>, + }, + DeletePEPNode { + node: String, + sender: oneshot::Sender<Result<(), PEPError>>, + }, + GetPEPItem { + jid: Option<BareJID>, + node: String, + id: String, + sender: oneshot::Sender<Result<pep::Item, PEPError>>, }, - /// change user nickname - ChangeNick(String, oneshot::Sender<Result<(), NickError>>), + /// change client user nickname + ChangeNick(Option<String>, oneshot::Sender<Result<(), NickError>>), + // // TODO + // GetNick(...), + // GetAvatar(...) // /// get capability node // GetCaps(String, oneshot::Sender<Result<Info, CapsError>>), + /// change client user avatar + ChangeAvatar( + Option<Vec<u8>>, + oneshot::Sender<Result<(), AvatarPublishError<Fs>>>, + ), } #[derive(Debug, Clone)] pub enum UpdateMessage { - Online(Online, Vec<Contact>), + Online(Online, Vec<(Contact, User)>), Offline(Offline), - /// received roster from jabber server (replace full app roster state with this) - /// is this needed? - FullRoster(Vec<Contact>), /// (only update app roster state, don't replace) - RosterUpdate(Contact), - RosterDelete(JID), + RosterUpdate(Contact, User), + RosterDelete(BareJID), /// presences should be stored with users in the ui, not contacts, as presences can be received from anyone Presence { from: JID, @@ -145,28 +190,44 @@ pub enum UpdateMessage { // TODO: receipts // MessageDispatched(Uuid), Message { - to: JID, + // TODO: rename to chat? + to: BareJID, + from: User, message: Message, }, MessageDelivery { id: Uuid, + chat: BareJID, delivery: Delivery, }, - SubscriptionRequest(jid::JID), + SubscriptionRequest(BareJID), NickChanged { - jid: JID, - nick: String, + jid: BareJID, + nick: Option<String>, + }, + AvatarChanged { + jid: BareJID, + id: Option<String>, }, } /// an xmpp client that is suited for a chat client use case #[derive(Debug)] -pub struct Client { - sender: mpsc::Sender<CoreClientCommand<Command>>, +pub struct Client<Fs: FileStore> { + sender: mpsc::Sender<CoreClientCommand<Command<Fs>>>, timeout: Duration, } -impl Clone for Client { +impl<Fs: FileStore> Client<Fs> { + pub fn with_timeout(&self, timeout: Duration) -> Self { + Self { + sender: self.sender.clone(), + timeout, + } + } +} + +impl<Fs: FileStore> Clone for Client<Fs> { fn clone(&self) -> Self { Self { sender: self.sender.clone(), @@ -175,32 +236,27 @@ impl Clone for Client { } } -impl Deref for Client { - type Target = mpsc::Sender<CoreClientCommand<Command>>; +impl<Fs: FileStore> Deref for Client<Fs> { + type Target = mpsc::Sender<CoreClientCommand<Command<Fs>>>; fn deref(&self) -> &Self::Target { &self.sender } } -impl DerefMut for Client { +impl<Fs: FileStore> DerefMut for Client<Fs> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.sender } } -impl Client { - pub async fn connect(&self) -> Result<(), ActorError> { - self.send(CoreClientCommand::Connect).await?; - Ok(()) - } - - pub async fn disconnect(&self, offline: Offline) -> Result<(), ActorError> { - self.send(CoreClientCommand::Disconnect).await?; - Ok(()) - } - - pub fn new(jid: JID, password: String, db: Db) -> (Self, mpsc::Receiver<UpdateMessage>) { +impl<Fs: FileStore + Clone + Send + Sync + 'static> Client<Fs> { + pub fn new( + jid: JID, + password: String, + db: Db, + file_store: Fs, + ) -> (Self, mpsc::Receiver<UpdateMessage>) { let (command_sender, command_receiver) = mpsc::channel(20); let (update_send, update_recv) = mpsc::channel(20); @@ -211,17 +267,38 @@ impl Client { let client = Self { sender: command_sender, // TODO: configure timeout - timeout: Duration::from_secs(10), + timeout: Duration::from_secs(20), }; - let logic = ClientLogic::new(client.clone(), jid.as_bare(), db, update_send); + let logic = ClientLogic::new(client.clone(), jid.to_bare(), db, update_send, file_store); - let actor: CoreClient<ClientLogic> = + let actor: CoreClient<ClientLogic<Fs>> = CoreClient::new(jid, password, command_receiver, None, sup_recv, logic); + tokio::spawn(async move { actor.run().await }); (client, update_recv) } +} + +impl<Fs: FileStore> Client<Fs> { + /// returns the resource + pub async fn connect(&self) -> Result<String, CommandError<ConnectionError>> { + let (send, recv) = oneshot::channel::<Result<String, ConnectionError>>(); + self.send(CoreClientCommand::Connect(send)) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let result = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(result) + } + + pub async fn disconnect(&self, offline: Offline) -> Result<(), ActorError> { + self.send(CoreClientCommand::Disconnect).await?; + Ok(()) + } pub async fn get_roster(&self) -> Result<Vec<Contact>, CommandError<RosterError>> { let (send, recv) = oneshot::channel(); @@ -235,6 +312,22 @@ impl Client { Ok(roster) } + pub async fn get_roster_with_users( + &self, + ) -> Result<Vec<(Contact, User)>, CommandError<RosterError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::GetRosterWithUsers( + send, + ))) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let roster = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(roster) + } + pub async fn get_chats(&self) -> Result<Vec<Chat>, CommandError<DatabaseError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::GetChats(send))) @@ -275,7 +368,23 @@ impl Client { Ok(chats) } - pub async fn get_chat(&self, jid: JID) -> Result<Chat, CommandError<DatabaseError>> { + pub async fn get_chats_ordered_with_latest_messages_and_users( + &self, + ) -> Result<Vec<((Chat, User), (Message, User))>, CommandError<DatabaseError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command( + Command::GetChatsOrderedWithLatestMessagesAndUsers(send), + )) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let chats = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(chats) + } + + pub async fn get_chat(&self, jid: BareJID) -> Result<Chat, CommandError<DatabaseError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::GetChat(jid, send))) .await @@ -287,9 +396,38 @@ impl Client { Ok(chat) } + pub async fn get_chat_and_user( + &self, + jid: BareJID, + ) -> Result<(Chat, User), CommandError<DatabaseError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::GetChatAndUser( + jid, send, + ))) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let result = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(result) + } + + pub async fn get_message(&self, id: Uuid) -> Result<Message, CommandError<DatabaseError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::GetMessage(id, send))) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let message = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(message) + } + pub async fn get_messages( &self, - jid: JID, + jid: BareJID, ) -> Result<Vec<Message>, CommandError<DatabaseError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::GetMessages(jid, send))) @@ -302,7 +440,24 @@ impl Client { Ok(messages) } - pub async fn delete_chat(&self, jid: JID) -> Result<(), CommandError<DatabaseError>> { + pub async fn get_messages_with_users( + &self, + jid: BareJID, + ) -> Result<Vec<(Message, User)>, CommandError<DatabaseError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::GetMessagesWithUsers( + jid, send, + ))) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let messages = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(messages) + } + + pub async fn delete_chat(&self, jid: BareJID) -> Result<(), CommandError<DatabaseError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::DeleteChat(jid, send))) .await @@ -326,7 +481,7 @@ impl Client { Ok(result) } - pub async fn get_user(&self, jid: JID) -> Result<User, CommandError<DatabaseError>> { + pub async fn get_user(&self, jid: BareJID) -> Result<User, CommandError<DatabaseError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::GetUser(jid, send))) .await @@ -338,7 +493,7 @@ impl Client { Ok(result) } - pub async fn add_contact(&self, jid: JID) -> Result<(), CommandError<RosterError>> { + pub async fn add_contact(&self, jid: BareJID) -> Result<(), CommandError<RosterError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::AddContact(jid, send))) .await @@ -350,7 +505,7 @@ impl Client { Ok(result) } - pub async fn buddy_request(&self, jid: JID) -> Result<(), CommandError<SubscribeError>> { + pub async fn buddy_request(&self, jid: BareJID) -> Result<(), CommandError<SubscribeError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::BuddyRequest(jid, send))) .await @@ -362,7 +517,10 @@ impl Client { Ok(result) } - pub async fn subscription_request(&self, jid: JID) -> Result<(), CommandError<SubscribeError>> { + pub async fn subscription_request( + &self, + jid: BareJID, + ) -> Result<(), CommandError<SubscribeError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::SubscriptionRequest( jid, send, @@ -376,7 +534,10 @@ impl Client { Ok(result) } - pub async fn accept_buddy_request(&self, jid: JID) -> Result<(), CommandError<SubscribeError>> { + pub async fn accept_buddy_request( + &self, + jid: BareJID, + ) -> Result<(), CommandError<SubscribeError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::AcceptBuddyRequest( jid, send, @@ -392,7 +553,7 @@ impl Client { pub async fn accept_subscription_request( &self, - jid: JID, + jid: BareJID, ) -> Result<(), CommandError<SubscribeError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command( @@ -407,7 +568,10 @@ impl Client { Ok(result) } - pub async fn unsubscribe_from_contact(&self, jid: JID) -> Result<(), CommandError<WriteError>> { + pub async fn unsubscribe_from_contact( + &self, + jid: BareJID, + ) -> Result<(), CommandError<WriteError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::UnsubscribeFromContact( jid, send, @@ -421,7 +585,7 @@ impl Client { Ok(result) } - pub async fn unsubscribe_contact(&self, jid: JID) -> Result<(), CommandError<WriteError>> { + pub async fn unsubscribe_contact(&self, jid: BareJID) -> Result<(), CommandError<WriteError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::UnsubscribeContact( jid, send, @@ -435,7 +599,7 @@ impl Client { Ok(result) } - pub async fn unfriend_contact(&self, jid: JID) -> Result<(), CommandError<WriteError>> { + pub async fn unfriend_contact(&self, jid: BareJID) -> Result<(), CommandError<WriteError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::UnfriendContact( jid, send, @@ -449,7 +613,7 @@ impl Client { Ok(result) } - pub async fn delete_contact(&self, jid: JID) -> Result<(), CommandError<RosterError>> { + pub async fn delete_contact(&self, jid: BareJID) -> Result<(), CommandError<RosterError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::DeleteContact( jid, send, @@ -465,7 +629,7 @@ impl Client { pub async fn update_contact( &self, - jid: JID, + jid: BareJID, update: ContactUpdate, ) -> Result<(), CommandError<RosterError>> { let (send, recv) = oneshot::channel(); @@ -493,7 +657,7 @@ impl Client { Ok(result) } - pub async fn send_message(&self, jid: JID, body: Body) -> Result<(), ActorError> { + pub async fn send_message(&self, jid: BareJID, body: Body) -> Result<(), ActorError> { self.send(CoreClientCommand::Command(Command::SendMessage(jid, body))) .await?; Ok(()) @@ -539,9 +703,9 @@ impl Client { &self, item: pep::Item, node: String, - ) -> Result<(), CommandError<PublishError>> { + ) -> Result<(), CommandError<PEPError>> { let (send, recv) = oneshot::channel(); - self.send(CoreClientCommand::Command(Command::Publish { + self.send(CoreClientCommand::Command(Command::PublishPEPItem { item, node, sender: send, @@ -555,7 +719,45 @@ impl Client { Ok(result) } - pub async fn change_nick(&self, nick: String) -> Result<(), CommandError<NickError>> { + pub async fn delete_pep_node(&self, node: String) -> Result<(), CommandError<PEPError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::DeletePEPNode { + node, + sender: send, + })) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let result = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(result) + } + + pub async fn get_pep_item( + &self, + // i think this is correct?, should not be able to send pep requests to a full jid. + jid: Option<BareJID>, + node: String, + id: String, + ) -> Result<pep::Item, CommandError<PEPError>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::GetPEPItem { + jid, + node, + id, + sender: send, + })) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let result = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(result) + } + + pub async fn change_nick(&self, nick: Option<String>) -> Result<(), CommandError<NickError>> { let (send, recv) = oneshot::channel(); self.send(CoreClientCommand::Command(Command::ChangeNick(nick, send))) .await @@ -566,10 +768,117 @@ impl Client { .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; Ok(result) } + + pub async fn change_avatar( + &self, + avatar: Option<Vec<u8>>, + ) -> Result<(), CommandError<AvatarPublishError<Fs>>> { + let (send, recv) = oneshot::channel(); + self.send(CoreClientCommand::Command(Command::ChangeAvatar( + avatar, send, + ))) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))?; + let result = timeout(self.timeout, recv) + .await + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))? + .map_err(|e| CommandError::Actor(Into::<ActorError>::into(e)))??; + Ok(result) + } } -impl From<Command> for CoreClientCommand<Command> { - fn from(value: Command) -> Self { +impl<Fs: FileStore> From<Command<Fs>> for CoreClientCommand<Command<Fs>> { + fn from(value: Command<Fs>) -> Self { CoreClientCommand::Command(value) } } + +#[cfg(test)] +mod tests { + use wasm_bindgen_test::*; + + use super::*; + + wasm_bindgen_test_configure!(run_in_browser); + + use crate::chat; + use crate::files::FilesMem; + use std::path::Path; + use tokio_with_wasm::alias as tokio; + + #[wasm_bindgen_test] + async fn login() -> () { + tracing_wasm::set_as_global_default(); + let db = Db::create_connect_and_migrate(Path::new("./filamento.db")) + .await + .unwrap(); + let (client, mut recv) = Client::new( + "test@blos.sm/testing2".try_into().unwrap(), + "slayed".to_string(), + db, + FilesMem::new(), + ); + + tokio::spawn(async move { + while let Some(msg) = recv.recv().await { + info!("{:#?}", msg) + } + }); + + client.connect().await.unwrap(); + // tokio::time::sleep(Duration::from_secs(5)).await; + info!("changing nick"); + client + .change_nick(Some("britney".to_string())) + .await + .unwrap(); + let mut data = include_bytes!("../files/britney_starbies.jpg"); + client.change_avatar(Some(data.to_vec())).await.unwrap(); + info!("sending message"); + client + .send_message( + BareJID::from_str("cel@blos.sm").unwrap(), + chat::Body { + body: "hallo!!!".to_string(), + }, + ) + .await + .unwrap(); + info!("sent message"); + client + .send_message( + BareJID::from_str("cel@blos.sm").unwrap(), + chat::Body { + body: "hallo 2".to_string(), + }, + ) + .await + .unwrap(); + // tokio::time::sleep(Duration::from_secs(15)).await; + // info!("sending disco query"); + // let info = client.disco_info(None, None).await.unwrap(); + // info!("got disco result: {:#?}", info); + // let items = client.disco_items(None, None).await.unwrap(); + // info!("got disco result: {:#?}", items); + // let info = client + // .disco_info(Some("blos.sm".parse().unwrap()), None) + // .await + // .unwrap(); + // info!("got disco result: {:#?}", info); + // let items = client + // .disco_items(Some("blos.sm".parse().unwrap()), None) + // .await + // .unwrap(); + // info!("got disco result: {:#?}", items); + // let info = client + // .disco_info(Some("pubsub.blos.sm".parse().unwrap()), None) + // .await + // .unwrap(); + // info!("got disco result: {:#?}", info); + // let items = client + // .disco_items(Some("pubsub.blos.sm".parse().unwrap()), None) + // .await + // .unwrap(); + // info!("got disco result: {:#?}", items); let mut jid: JID = "test@blos.sm".try_into().unwrap(); + } +} |