aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar cel 🌸 <cel@bunny.garden>2025-06-01 13:31:52 +0100
committerLibravatar cel 🌸 <cel@bunny.garden>2025-06-01 13:31:52 +0100
commitc6bdf077b82b30f8228b56702bd3ee71d92b3910 (patch)
treedb12501d5d60906b77b19c1395a522967957c715
parentc196aecbe7b3b29fbfff9e997478688e6833b7f3 (diff)
downloadluz-c6bdf077b82b30f8228b56702bd3ee71d92b3910.tar.gz
luz-c6bdf077b82b30f8228b56702bd3ee71d92b3910.tar.bz2
luz-c6bdf077b82b30f8228b56702bd3ee71d92b3910.zip
refactor: utilise new jid type safetyHEADmainjid-refactor
-rw-r--r--.helix/languages.toml4
-rw-r--r--filamento/src/caps.rs2
-rw-r--r--filamento/src/chat.rs10
-rw-r--r--filamento/src/db.rs176
-rw-r--r--filamento/src/error.rs3
-rw-r--r--filamento/src/lib.rs126
-rw-r--r--filamento/src/logic/local_only.rs14
-rw-r--r--filamento/src/logic/mod.rs8
-rw-r--r--filamento/src/logic/offline.rs23
-rw-r--r--filamento/src/logic/online.rs101
-rw-r--r--filamento/src/logic/process_stanza.rs107
-rw-r--r--filamento/src/roster.rs4
-rw-r--r--filamento/src/user.rs4
-rw-r--r--lampada/src/connection/mod.rs27
-rw-r--r--lampada/src/error.rs2
-rw-r--r--lampada/src/lib.rs40
-rw-r--r--luz/src/client/tcp.rs19
-rw-r--r--luz/src/client/ws.rs11
-rw-r--r--luz/src/connection/tcp.rs2
-rw-r--r--luz/src/error.rs4
-rw-r--r--luz/src/jabber_stream.rs23
-rw-r--r--stanza/src/bind.rs4
-rw-r--r--stanza/src/rfc_7395.rs10
-rw-r--r--stanza/src/roster.rs4
-rw-r--r--stanza/src/stream.rs17
-rw-r--r--stanza/src/xep_0060/owner.rs4
26 files changed, 392 insertions, 357 deletions
diff --git a/.helix/languages.toml b/.helix/languages.toml
index 7662fff..02fab3a 100644
--- a/.helix/languages.toml
+++ b/.helix/languages.toml
@@ -1,9 +1,9 @@
[language-server.rust-analyzer]
command = "rust-analyzer"
-environment = { "DATABASE_URL" = "sqlite://filamento/filamento.db" }
+# environment = { "DATABASE_URL" = "sqlite://filamento/filamento.db" }
# checkOnSave.overrideCommand = "cargo check --message-format=json -p luz",
# check.overrideCommand="cargo check --message-format=json -p luz",
# check.workspace = false,
# cargo.target = "wasm32-unknown-unknown",
-config = { cargo.target = "wasm32-unknown-unknown", cargo.features = ["jid/rusqlite", "stanza/rfc_6121", "stanza/xep_0203", "stanza/rfc_7395", "stanza/xep_0030", "stanza/xep_0060", "stanza/xep_0172", "stanza/xep_0390", "stanza/xep_0128", "stanza/xep_0115", "stanza/xep_0084", "uuid/v4", "tokio/full", "rsasl/provider_base64", "rsasl/plain", "rsasl/config_builder", "rsasl/scram-sha-1", "stanza/xep_0156"] }
+# config = { cargo.target = "wasm32-unknown-unknown", cargo.features = ["jid/rusqlite", "stanza/rfc_6121", "stanza/xep_0203", "stanza/rfc_7395", "stanza/xep_0030", "stanza/xep_0060", "stanza/xep_0172", "stanza/xep_0390", "stanza/xep_0128", "stanza/xep_0115", "stanza/xep_0084", "uuid/v4", "tokio/full", "rsasl/provider_base64", "rsasl/plain", "rsasl/config_builder", "rsasl/scram-sha-1", "stanza/xep_0156"] }
# "sqlx/sqlite", "sqlx/runtime-tokio", "sqlx/uuid", "sqlx/chrono", "jid/sqlx",
diff --git a/filamento/src/caps.rs b/filamento/src/caps.rs
index 43f1cf4..e0587ff 100644
--- a/filamento/src/caps.rs
+++ b/filamento/src/caps.rs
@@ -377,7 +377,7 @@ pub fn node_to_hash(node: String) -> Result<Hash, HashNodeConversionError> {
#[cfg(test)]
mod tests {
- use peanuts::{Writer, element::IntoElement, loggable::Loggable};
+ use peanuts::Writer;
use stanza::{
xep_0004::{Field, FieldType, Value, X, XType},
xep_0030::info::{Feature, Identity},
diff --git a/filamento/src/chat.rs b/filamento/src/chat.rs
index 5f58866..c02654f 100644
--- a/filamento/src/chat.rs
+++ b/filamento/src/chat.rs
@@ -1,7 +1,7 @@
use std::fmt::{Display, Write};
use chrono::{DateTime, Utc};
-use jid::JID;
+use jid::{BareJID, JID};
use rusqlite::{
ToSql,
types::{FromSql, ToSqlOutput, Value},
@@ -15,7 +15,7 @@ pub struct Message {
pub id: Uuid,
// does not contain full user information
// bare jid (for now)
- pub from: JID,
+ pub from: BareJID,
pub delivery: Option<Delivery>,
pub timestamp: DateTime<Utc>,
// TODO: originally_from
@@ -97,7 +97,7 @@ pub struct Body {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "reactive_stores", derive(reactive_stores::Store))]
pub struct Chat {
- pub correspondent: JID,
+ pub correspondent: BareJID,
pub have_chatted: bool,
// pub unread_messages: i32,
// pub latest_message: Message,
@@ -109,13 +109,13 @@ pub struct Chat {
pub enum ChatUpdate {}
impl Chat {
- pub fn new(correspondent: JID, have_chatted: bool) -> Self {
+ pub fn new(correspondent: BareJID, have_chatted: bool) -> Self {
Self {
correspondent,
have_chatted,
}
}
- pub fn correspondent(&self) -> &JID {
+ pub fn correspondent(&self) -> &BareJID {
&self.correspondent
}
}
diff --git a/filamento/src/db.rs b/filamento/src/db.rs
index bac1b7c..385382a 100644
--- a/filamento/src/db.rs
+++ b/filamento/src/db.rs
@@ -2,7 +2,7 @@ use core::fmt::Display;
use std::{collections::HashSet, ops::Deref, path::Path, sync::Arc};
use chrono::{DateTime, Utc};
-use jid::JID;
+use jid::{BareJID, FullJID, JID};
use rusqlite::{Connection, OptionalExtension};
use tokio::sync::{Mutex, MutexGuard};
use tokio::sync::{mpsc, oneshot};
@@ -152,7 +152,7 @@ impl Db {
}
// TODO: this is not a 'read' user
- pub(crate) async fn read_user(&self, user: JID) -> Result<User, Error> {
+ pub(crate) async fn read_user(&self, user: BareJID) -> Result<User, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::ReadUser { user, result };
self.sender.send(command);
@@ -161,7 +161,7 @@ impl Db {
}
/// returns whether or not the nickname was updated
- pub(crate) async fn delete_user_nick(&self, jid: JID) -> Result<bool, Error> {
+ pub(crate) async fn delete_user_nick(&self, jid: BareJID) -> Result<bool, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::DeleteUserNick { jid, result };
self.sender.send(command);
@@ -170,7 +170,7 @@ impl Db {
}
/// returns whether or not the nickname was updated
- pub(crate) async fn upsert_user_nick(&self, jid: JID, nick: String) -> Result<bool, Error> {
+ pub(crate) async fn upsert_user_nick(&self, jid: BareJID, nick: String) -> Result<bool, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::UpsertUserNick { jid, nick, result };
self.sender.send(command);
@@ -181,7 +181,7 @@ impl Db {
/// returns whether or not the avatar was updated, and the file to delete if there existed an old avatar
pub(crate) async fn delete_user_avatar(
&self,
- jid: JID,
+ jid: BareJID,
) -> Result<(bool, Option<String>), Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::DeleteUserAvatar { jid, result };
@@ -193,7 +193,7 @@ impl Db {
/// returns whether or not the avatar was updated, and the file to delete if there existed an old avatar
pub(crate) async fn upsert_user_avatar(
&self,
- jid: JID,
+ jid: BareJID,
avatar: String,
) -> Result<(bool, Option<String>), Error> {
let (result, recv) = oneshot::channel();
@@ -228,7 +228,7 @@ impl Db {
result
}
- pub(crate) async fn read_contact(&self, contact: JID) -> Result<Contact, Error> {
+ pub(crate) async fn read_contact(&self, contact: BareJID) -> Result<Contact, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::ReadContact { contact, result };
self.sender.send(command);
@@ -236,7 +236,10 @@ impl Db {
result
}
- pub(crate) async fn read_contact_opt(&self, contact: JID) -> Result<Option<Contact>, Error> {
+ pub(crate) async fn read_contact_opt(
+ &self,
+ contact: BareJID,
+ ) -> Result<Option<Contact>, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::ReadContactOpt { contact, result };
self.sender.send(command);
@@ -261,7 +264,7 @@ impl Db {
result
}
- pub(crate) async fn delete_contact(&self, contact: JID) -> Result<(), Error> {
+ pub(crate) async fn delete_contact(&self, contact: BareJID) -> Result<(), Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::DeleteContact { contact, result };
self.sender.send(command);
@@ -305,7 +308,7 @@ impl Db {
// TODO: what happens if a correspondent changes from a user to a contact? maybe just have correspondent be a user, then have the client make the user show up as a contact in ui if they are in the loaded roster.
- pub(crate) async fn read_chat(&self, chat: JID) -> Result<Chat, Error> {
+ pub(crate) async fn read_chat(&self, chat: BareJID) -> Result<Chat, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::ReadChat { chat, result };
self.sender.send(command);
@@ -313,7 +316,7 @@ impl Db {
result
}
- pub(crate) async fn read_chat_and_user(&self, chat: JID) -> Result<(Chat, User), Error> {
+ pub(crate) async fn read_chat_and_user(&self, chat: BareJID) -> Result<(Chat, User), Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::ReadChatAndUser { chat, result };
self.sender.send(command);
@@ -321,7 +324,7 @@ impl Db {
result
}
- pub(crate) async fn mark_chat_as_chatted(&self, chat: JID) -> Result<(), Error> {
+ pub(crate) async fn mark_chat_as_chatted(&self, chat: BareJID) -> Result<(), Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::MarkChatAsChatted { chat, result };
self.sender.send(command);
@@ -332,7 +335,7 @@ impl Db {
pub(crate) async fn update_chat_correspondent(
&self,
old_chat: Chat,
- new_correspondent: JID,
+ new_correspondent: BareJID,
) -> Result<Chat, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::UpdateChatCorrespondent {
@@ -347,7 +350,7 @@ impl Db {
// pub(crate) async fn update_chat
- pub(crate) async fn delete_chat(&self, chat: JID) -> Result<(), Error> {
+ pub(crate) async fn delete_chat(&self, chat: BareJID) -> Result<(), Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::DeleteChat { chat, result };
self.sender.send(command);
@@ -403,8 +406,8 @@ impl Db {
pub(crate) async fn create_message(
&self,
message: Message,
- chat: JID,
- from: JID,
+ chat: BareJID,
+ from: FullJID,
) -> Result<(), Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::CreateMessage {
@@ -418,7 +421,7 @@ impl Db {
result
}
- pub(crate) async fn upsert_chat_and_user(&self, chat: JID) -> Result<bool, Error> {
+ pub(crate) async fn upsert_chat_and_user(&self, chat: BareJID) -> Result<bool, Error> {
let (result, recv) = oneshot::channel();
let command = DbCommand::UpsertChatAndUser { chat, result };
self.sender.send(command);
@@ -432,10 +435,8 @@ impl Db {
&self,
message: Message,
// TODO: enforce two kinds of jid. bare and full
- // must be bare jid
- chat: JID,
- // full jid
- from: JID,
+ chat: BareJID,
+ from: FullJID,
) -> Result<(), Error> {
tracing::info!("MSGDEBUG create_message_with_user_resource exists");
let (result, recv) = oneshot::channel();
@@ -483,9 +484,9 @@ impl Db {
DeleteCachedStatus => delete_cached_status() -> ();
UpsertCachedStatus => upsert_cached_status(status: Online) -> ();
ReadCachedStatus => read_cached_status() -> Online;
- ReadMessageHistoryWithUsers => read_message_history_with_users(chat: JID) -> Vec<(Message, User)>;
+ ReadMessageHistoryWithUsers => read_message_history_with_users(chat: BareJID) -> Vec<(Message, User)>;
// TODO: paging
- ReadMessageHistory => read_message_history(chat: JID) -> Vec<Message>;
+ ReadMessageHistory => read_message_history(chat: BareJID) -> Vec<Message>;
ReadMessage => read_message(message: Uuid) -> Message;
DeleteMessage => delete_message(message: Uuid) -> ()
);
@@ -515,24 +516,24 @@ pub enum DbCommand {
result: oneshot::Sender<Result<(), Error>>,
},
ReadUser {
- user: JID,
+ user: BareJID,
result: oneshot::Sender<Result<User, Error>>,
},
DeleteUserNick {
- jid: JID,
+ jid: BareJID,
result: oneshot::Sender<Result<bool, Error>>,
},
UpsertUserNick {
- jid: JID,
+ jid: BareJID,
nick: String,
result: oneshot::Sender<Result<bool, Error>>,
},
DeleteUserAvatar {
- jid: JID,
+ jid: BareJID,
result: oneshot::Sender<Result<(bool, Option<String>), Error>>,
},
UpsertUserAvatar {
- jid: JID,
+ jid: BareJID,
avatar: String,
result: oneshot::Sender<Result<(bool, Option<String>), Error>>,
},
@@ -545,11 +546,11 @@ pub enum DbCommand {
result: oneshot::Sender<Result<(), Error>>,
},
ReadContact {
- contact: JID,
+ contact: BareJID,
result: oneshot::Sender<Result<Contact, Error>>,
},
ReadContactOpt {
- contact: JID,
+ contact: BareJID,
result: oneshot::Sender<Result<Option<Contact>, Error>>,
},
UpdateContact {
@@ -561,7 +562,7 @@ pub enum DbCommand {
result: oneshot::Sender<Result<(), Error>>,
},
DeleteContact {
- contact: JID,
+ contact: BareJID,
result: oneshot::Sender<Result<(), Error>>,
},
ReplaceCachedRoster {
@@ -579,24 +580,24 @@ pub enum DbCommand {
result: oneshot::Sender<Result<(), Error>>,
},
ReadChat {
- chat: JID,
+ chat: BareJID,
result: oneshot::Sender<Result<Chat, Error>>,
},
ReadChatAndUser {
- chat: JID,
+ chat: BareJID,
result: oneshot::Sender<Result<(Chat, User), Error>>,
},
MarkChatAsChatted {
- chat: JID,
+ chat: BareJID,
result: oneshot::Sender<Result<(), Error>>,
},
UpdateChatCorrespondent {
old_chat: Chat,
- new_correspondent: JID,
+ new_correspondent: BareJID,
result: oneshot::Sender<Result<Chat, Error>>,
},
DeleteChat {
- chat: JID,
+ chat: BareJID,
result: oneshot::Sender<Result<(), Error>>,
},
ReadChats {
@@ -621,18 +622,18 @@ pub enum DbCommand {
// },
CreateMessage {
message: Message,
- chat: JID,
- from: JID,
+ chat: BareJID,
+ from: FullJID,
result: oneshot::Sender<Result<(), Error>>,
},
UpsertChatAndUser {
- chat: JID,
+ chat: BareJID,
result: oneshot::Sender<Result<bool, Error>>,
},
CreateMessageWithUserResource {
message: Message,
- chat: JID,
- from: JID,
+ chat: BareJID,
+ from: FullJID,
result: oneshot::Sender<Result<(), Error>>,
},
UpdateMessageDelivery {
@@ -649,11 +650,11 @@ pub enum DbCommand {
result: oneshot::Sender<Result<Message, Error>>,
},
ReadMessageHistory {
- chat: JID,
+ chat: BareJID,
result: oneshot::Sender<Result<Vec<Message>, Error>>,
},
ReadMessageHistoryWithUsers {
- chat: JID,
+ chat: BareJID,
result: oneshot::Sender<Result<Vec<(Message, User)>, Error>>,
},
ReadCachedStatus {
@@ -823,7 +824,7 @@ impl DbActor {
result.send(self.read_contact(contact));
}
DbCommand::ReadContactOpt { contact, result } => {
- result.send(self.read_contact_opt(&contact));
+ result.send(self.read_contact_opt(contact));
}
DbCommand::UpdateContact { contact, result } => {
result.send(self.update_contact(contact));
@@ -951,7 +952,7 @@ impl DbActor {
}
// TODO: this is not a 'read' user
- pub(crate) fn read_user(&self, user: JID) -> Result<User, Error> {
+ pub(crate) fn read_user(&self, user: BareJID) -> Result<User, Error> {
let db = &self.db;
let user_opt = db
.query_row(
@@ -980,7 +981,7 @@ impl DbActor {
}
/// returns whether or not the nickname was updated
- pub(crate) fn delete_user_nick(&self, jid: JID) -> Result<bool, Error> {
+ pub(crate) fn delete_user_nick(&self, jid: BareJID) -> Result<bool, Error> {
let rows_affected;
{
rows_affected = self.db.execute("insert into users (jid, nick) values (?1, ?2) on conflict do update set nick = ?3 where nick is not ?4", (jid, None::<String>, None::<String>, None::<String>))?;
@@ -993,7 +994,7 @@ impl DbActor {
}
/// returns whether or not the nickname was updated
- pub(crate) fn upsert_user_nick(&self, jid: JID, nick: String) -> Result<bool, Error> {
+ pub(crate) fn upsert_user_nick(&self, jid: BareJID, nick: String) -> Result<bool, Error> {
let rows_affected;
{
rows_affected = self.db.execute("insert into users (jid, nick) values (?1, ?2) on conflict do update set nick = ?3 where nick is not ?4", (jid, &nick, &nick, &nick))?;
@@ -1006,7 +1007,7 @@ impl DbActor {
}
/// returns whether or not the avatar was updated, and the file to delete if there existed an old avatar
- pub(crate) fn delete_user_avatar(&self, jid: JID) -> Result<(bool, Option<String>), Error> {
+ pub(crate) fn delete_user_avatar(&self, jid: BareJID) -> Result<(bool, Option<String>), Error> {
let (old_avatar, rows_affected): (Option<String>, _);
{
let db = &self.db;
@@ -1027,7 +1028,7 @@ impl DbActor {
/// returns whether or not the avatar was updated, and the file to delete if there existed an old avatar
pub(crate) fn upsert_user_avatar(
&self,
- jid: JID,
+ jid: BareJID,
avatar: String,
) -> Result<(bool, Option<String>), Error> {
let (old_avatar, rows_affected): (Option<String>, _);
@@ -1081,7 +1082,7 @@ impl DbActor {
Ok(())
}
- pub(crate) fn read_contact(&self, contact: JID) -> Result<Contact, Error> {
+ pub(crate) fn read_contact(&self, contact: BareJID) -> Result<Contact, Error> {
let db = &self.db;
let mut contact_item = db.query_row(
"select user_jid, name, subscription from roster where user_jid = ?1",
@@ -1103,7 +1104,7 @@ impl DbActor {
Ok(contact_item)
}
- pub(crate) fn read_contact_opt(&self, contact: &JID) -> Result<Option<Contact>, Error> {
+ pub(crate) fn read_contact_opt(&self, contact: BareJID) -> Result<Option<Contact>, Error> {
let db = &self.db;
let contact_item = db
.query_row(
@@ -1183,7 +1184,7 @@ impl DbActor {
Ok(())
}
- pub(crate) fn delete_contact(&self, contact: JID) -> Result<(), Error> {
+ pub(crate) fn delete_contact(&self, contact: BareJID) -> Result<(), Error> {
self.db
.execute("delete from roster where user_jid = ?1", [&contact])?;
Ok(())
@@ -1261,19 +1262,21 @@ impl DbActor {
// TODO: what happens if a correspondent changes from a user to a contact? maybe just have correspondent be a user, then have the client make the user show up as a contact in ui if they are in the loaded roster.
- /// should be a bare jid
/// TODO: this is NOT a read
- pub(crate) fn read_chat(&self, chat: JID) -> Result<Chat, Error> {
- let chat_opt = self.db.query_row(
- "select correspondent, have_chatted from chats where correspondent = ?1",
- [&chat],
- |row| {
- Ok(Chat {
- correspondent: row.get(0)?,
- have_chatted: row.get(1)?,
- })
- },
- ).optional()?;
+ pub(crate) fn read_chat(&self, chat: BareJID) -> Result<Chat, Error> {
+ let chat_opt = self
+ .db
+ .query_row(
+ "select correspondent, have_chatted from chats where correspondent = ?1",
+ [&chat],
+ |row| {
+ Ok(Chat {
+ correspondent: row.get(0)?,
+ have_chatted: row.get(1)?,
+ })
+ },
+ )
+ .optional()?;
match chat_opt {
Some(chat) => return Ok(chat),
None => {
@@ -1287,7 +1290,7 @@ impl DbActor {
}
}
- pub(crate) fn read_chat_and_user(&self, chat: JID) -> Result<(Chat, User), Error> {
+ pub(crate) fn read_chat_and_user(&self, chat: BareJID) -> Result<(Chat, User), Error> {
let user = self.read_user(chat.clone())?;
let chat_opt = self.db.query_row(
"select correspondent, have_chatted, jid, nick, avatar from chats join users on correspondent = jid where correspondent = ?1",
@@ -1319,7 +1322,7 @@ impl DbActor {
}
}
- pub(crate) fn mark_chat_as_chatted(&self, chat: JID) -> Result<(), Error> {
+ pub(crate) fn mark_chat_as_chatted(&self, chat: BareJID) -> Result<(), Error> {
self.db.execute(
"update chats set have_chatted = true where correspondent = ?1",
[chat],
@@ -1330,7 +1333,7 @@ impl DbActor {
pub(crate) fn update_chat_correspondent(
&self,
old_chat: Chat,
- new_correspondent: JID,
+ new_correspondent: BareJID,
) -> Result<Chat, Error> {
let new_jid = &new_correspondent;
let old_jid = old_chat.correspondent();
@@ -1347,7 +1350,7 @@ impl DbActor {
// pub(crate) fn update_chat
- pub(crate) fn delete_chat(&self, chat: JID) -> Result<(), Error> {
+ pub(crate) fn delete_chat(&self, chat: BareJID) -> Result<(), Error> {
self.db
.execute("delete from chats where correspondent = ?1", [chat])?;
Ok(())
@@ -1457,7 +1460,7 @@ impl DbActor {
}
#[tracing::instrument]
- fn read_chat_id(&self, chat: JID) -> Result<Uuid, Error> {
+ fn read_chat_id(&self, chat: BareJID) -> Result<Uuid, Error> {
let chat_id = self.db.query_row(
"select id from chats where correspondent = ?1",
[chat],
@@ -1483,8 +1486,8 @@ impl DbActor {
pub(crate) fn create_message(
&self,
message: Message,
- chat: JID,
- from: JID,
+ chat: BareJID,
+ from: FullJID,
) -> Result<(), Error> {
let from_jid = from.as_bare();
let chat_id = self.read_chat_id(chat)?;
@@ -1493,18 +1496,17 @@ impl DbActor {
Ok(())
}
- pub(crate) fn upsert_chat_and_user(&self, chat: &JID) -> Result<bool, Error> {
- let bare_chat = chat.as_bare();
+ pub(crate) fn upsert_chat_and_user(&self, chat: &BareJID) -> Result<bool, Error> {
let db = &self.db;
db.execute(
"insert into users (jid) values (?1) on conflict do nothing",
- [&bare_chat],
+ [&chat],
)?;
let id = Uuid::new_v4();
- db.execute("insert into chats (id, correspondent, have_chatted) values (?1, ?2, ?3) on conflict do nothing", (id, &bare_chat, false))?;
+ db.execute("insert into chats (id, correspondent, have_chatted) values (?1, ?2, ?3) on conflict do nothing", (id, &chat, false))?;
let chat = db.query_row(
"select correspondent, have_chatted from chats where correspondent = ?1",
- [&bare_chat],
+ [&chat],
|row| {
Ok(Chat {
correspondent: row.get(0)?,
@@ -1520,21 +1522,15 @@ impl DbActor {
pub(crate) fn create_message_with_user_resource(
&self,
message: Message,
- // TODO: enforce two kinds of jid. bare and full
- // must be bare jid
- chat: JID,
- // full jid
- from: JID,
+ chat: BareJID,
+ from: FullJID,
) -> Result<(), Error> {
let from_jid = from.as_bare();
- let chat = chat.as_bare();
tracing::debug!("creating resource");
- if let Some(resource) = &from.resourcepart {
- self.db.execute(
- "insert into resources (bare_jid, resource) values (?1, ?2) on conflict do nothing",
- (&from_jid, resource),
- )?;
- }
+ self.db.execute(
+ "insert into resources (bare_jid, resource) values (?1, ?2) on conflict do nothing",
+ (&from_jid, &from.resourcepart),
+ )?;
self.create_message(message, chat, from)?;
Ok(())
}
@@ -1588,7 +1584,7 @@ impl DbActor {
}
// TODO: paging
- pub(crate) fn read_message_history(&self, chat: JID) -> Result<Vec<Message>, Error> {
+ pub(crate) fn read_message_history(&self, chat: BareJID) -> Result<Vec<Message>, Error> {
let chat_id = self.read_chat_id(chat)?;
let messages = self
.db
@@ -1611,7 +1607,7 @@ impl DbActor {
pub(crate) fn read_message_history_with_users(
&self,
- chat: JID,
+ chat: BareJID,
) -> Result<Vec<(Message, User)>, Error> {
let chat_id = self.read_chat_id(chat)?;
let messages = self
diff --git a/filamento/src/error.rs b/filamento/src/error.rs
index f9f9199..721d532 100644
--- a/filamento/src/error.rs
+++ b/filamento/src/error.rs
@@ -3,6 +3,7 @@ use std::{num::TryFromIntError, string::FromUtf8Error, sync::Arc};
use base64::DecodeError;
use image::ImageError;
use jid::JID;
+use jid::JIDError;
use lampada::error::{ActorError, ReadError, WriteError};
use stanza::client::{Stanza, iq::Query};
use thiserror::Error;
@@ -332,6 +333,8 @@ pub enum PresenceError {
MissingFrom,
#[error("stanza error: {0:?}")]
StanzaError(Option<stanza::client::error::Error>),
+ #[error("received subscription request from a non-bare jid")]
+ InvalidSubscriptionRequest(#[from] JIDError),
}
#[derive(Debug, Error, Clone)]
diff --git a/filamento/src/lib.rs b/filamento/src/lib.rs
index 068bfe8..d3033b7 100644
--- a/filamento/src/lib.rs
+++ b/filamento/src/lib.rs
@@ -16,7 +16,7 @@ use error::{
};
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},
@@ -68,45 +68,55 @@ pub enum Command<Fs: FileStore> {
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(JID, oneshot::Sender<Result<(Chat, User), DatabaseError>>),
+ 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(JID, oneshot::Sender<Result<Vec<Message>, DatabaseError>>),
+ GetMessages(
+ BareJID,
+ oneshot::Sender<Result<Vec<Message>, DatabaseError>>,
+ ),
/// get message history for chat (does appropriate mam things)
// TODO: paging and filtering
GetMessagesWithUsers(
- JID,
+ 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
@@ -120,7 +130,7 @@ pub enum Command<Fs: FileStore> {
// 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
@@ -146,7 +156,7 @@ pub enum Command<Fs: FileStore> {
sender: oneshot::Sender<Result<(), PEPError>>,
},
GetPEPItem {
- jid: Option<JID>,
+ jid: Option<BareJID>,
node: String,
id: String,
sender: oneshot::Sender<Result<pep::Item, PEPError>>,
@@ -171,7 +181,7 @@ pub enum UpdateMessage {
Offline(Offline),
/// (only update app roster state, don't replace)
RosterUpdate(Contact, User),
- RosterDelete(JID),
+ RosterDelete(BareJID),
/// presences should be stored with users in the ui, not contacts, as presences can be received from anyone
Presence {
from: JID,
@@ -180,22 +190,23 @@ pub enum UpdateMessage {
// TODO: receipts
// MessageDispatched(Uuid),
Message {
- to: JID,
+ // TODO: rename to chat?
+ to: BareJID,
from: User,
message: Message,
},
MessageDelivery {
id: Uuid,
- chat: JID,
+ chat: BareJID,
delivery: Delivery,
},
- SubscriptionRequest(jid::JID),
+ SubscriptionRequest(BareJID),
NickChanged {
- jid: JID,
+ jid: BareJID,
nick: Option<String>,
},
AvatarChanged {
- jid: JID,
+ jid: BareJID,
id: Option<String>,
},
}
@@ -259,7 +270,7 @@ impl<Fs: FileStore + Clone + Send + Sync + 'static> Client<Fs> {
timeout: Duration::from_secs(20),
};
- let logic = ClientLogic::new(client.clone(), jid.as_bare(), db, update_send, file_store);
+ let logic = ClientLogic::new(client.clone(), jid.to_bare(), db, update_send, file_store);
let actor: CoreClient<ClientLogic<Fs>> =
CoreClient::new(jid, password, command_receiver, None, sup_recv, logic);
@@ -373,7 +384,7 @@ impl<Fs: FileStore> Client<Fs> {
Ok(chats)
}
- pub async fn get_chat(&self, jid: JID) -> Result<Chat, CommandError<DatabaseError>> {
+ 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
@@ -385,12 +396,17 @@ impl<Fs: FileStore> Client<Fs> {
Ok(chat)
}
- pub async fn get_chat_and_user(&self, jid: JID) -> Result<(Chat, User), CommandError<DatabaseError>> {
+ 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)
+ 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)))??;
@@ -411,7 +427,7 @@ impl<Fs: FileStore> Client<Fs> {
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)))
@@ -426,7 +442,7 @@ impl<Fs: FileStore> Client<Fs> {
pub async fn get_messages_with_users(
&self,
- jid: JID,
+ jid: BareJID,
) -> Result<Vec<(Message, User)>, CommandError<DatabaseError>> {
let (send, recv) = oneshot::channel();
self.send(CoreClientCommand::Command(Command::GetMessagesWithUsers(
@@ -441,7 +457,7 @@ impl<Fs: FileStore> Client<Fs> {
Ok(messages)
}
- pub async fn delete_chat(&self, jid: JID) -> Result<(), CommandError<DatabaseError>> {
+ 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
@@ -465,7 +481,7 @@ impl<Fs: FileStore> Client<Fs> {
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
@@ -477,7 +493,7 @@ impl<Fs: FileStore> Client<Fs> {
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
@@ -489,7 +505,7 @@ impl<Fs: FileStore> Client<Fs> {
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
@@ -501,7 +517,10 @@ impl<Fs: FileStore> Client<Fs> {
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,
@@ -515,7 +534,10 @@ impl<Fs: FileStore> Client<Fs> {
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,
@@ -531,7 +553,7 @@ impl<Fs: FileStore> Client<Fs> {
pub async fn accept_subscription_request(
&self,
- jid: JID,
+ jid: BareJID,
) -> Result<(), CommandError<SubscribeError>> {
let (send, recv) = oneshot::channel();
self.send(CoreClientCommand::Command(
@@ -546,7 +568,10 @@ impl<Fs: FileStore> Client<Fs> {
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,
@@ -560,7 +585,7 @@ impl<Fs: FileStore> Client<Fs> {
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,
@@ -574,7 +599,7 @@ impl<Fs: FileStore> Client<Fs> {
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,
@@ -588,7 +613,7 @@ impl<Fs: FileStore> Client<Fs> {
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,
@@ -604,7 +629,7 @@ impl<Fs: FileStore> Client<Fs> {
pub async fn update_contact(
&self,
- jid: JID,
+ jid: BareJID,
update: ContactUpdate,
) -> Result<(), CommandError<RosterError>> {
let (send, recv) = oneshot::channel();
@@ -632,7 +657,7 @@ impl<Fs: FileStore> Client<Fs> {
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(())
@@ -711,7 +736,8 @@ impl<Fs: FileStore> Client<Fs> {
pub async fn get_pep_item(
&self,
- jid: Option<JID>,
+ // 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>> {
@@ -811,7 +837,7 @@ mod tests {
info!("sending message");
client
.send_message(
- JID::from_str("cel@blos.sm").unwrap(),
+ BareJID::from_str("cel@blos.sm").unwrap(),
chat::Body {
body: "hallo!!!".to_string(),
},
@@ -821,7 +847,7 @@ mod tests {
info!("sent message");
client
.send_message(
- JID::from_str("cel@blos.sm").unwrap(),
+ BareJID::from_str("cel@blos.sm").unwrap(),
chat::Body {
body: "hallo 2".to_string(),
},
diff --git a/filamento/src/logic/local_only.rs b/filamento/src/logic/local_only.rs
index f5705f4..7f3a2e6 100644
--- a/filamento/src/logic/local_only.rs
+++ b/filamento/src/logic/local_only.rs
@@ -1,4 +1,4 @@
-use jid::JID;
+use jid::{BareJID, JID};
use uuid::Uuid;
use crate::{
@@ -39,14 +39,14 @@ pub async fn handle_get_chats_ordered_with_latest_messages_and_users<Fs: FileSto
pub async fn handle_get_chat<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
- jid: JID,
+ jid: BareJID,
) -> Result<Chat, DatabaseError> {
Ok(logic.db().read_chat(jid).await?)
}
pub async fn handle_get_chat_and_user<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
- jid: JID,
+ jid: BareJID,
) -> Result<(Chat, User), DatabaseError> {
Ok(logic.db().read_chat_and_user(jid).await?)
}
@@ -60,21 +60,21 @@ pub async fn handle_get_message<Fs: FileStore + Clone>(
pub async fn handle_get_messages<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
- jid: JID,
+ jid: BareJID,
) -> Result<Vec<Message>, DatabaseError> {
Ok(logic.db().read_message_history(jid).await?)
}
pub async fn handle_get_messages_with_users<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
- jid: JID,
+ jid: BareJID,
) -> Result<Vec<(Message, User)>, DatabaseError> {
Ok(logic.db().read_message_history_with_users(jid).await?)
}
pub async fn handle_delete_chat<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
- jid: JID,
+ jid: BareJID,
) -> Result<(), DatabaseError> {
Ok(logic.db().delete_chat(jid).await?)
}
@@ -88,7 +88,7 @@ pub async fn handle_delete_messaage<Fs: FileStore + Clone>(
pub async fn handle_get_user<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
- jid: JID,
+ jid: BareJID,
) -> Result<User, DatabaseError> {
Ok(logic.db().read_user(jid).await?)
}
diff --git a/filamento/src/logic/mod.rs b/filamento/src/logic/mod.rs
index 5e05dac..146f3b0 100644
--- a/filamento/src/logic/mod.rs
+++ b/filamento/src/logic/mod.rs
@@ -1,6 +1,6 @@
use std::{collections::HashMap, sync::Arc};
-use jid::JID;
+use jid::{BareJID, JID};
use lampada::{Connected, Logic, error::ReadError};
use stanza::client::Stanza;
use tokio::sync::{Mutex, mpsc, oneshot};
@@ -25,7 +25,7 @@ mod process_stanza;
#[derive(Clone)]
pub struct ClientLogic<Fs: FileStore> {
client: Client<Fs>,
- bare_jid: JID,
+ jid: BareJID,
db: Db,
pending: Pending,
update_sender: mpsc::Sender<UpdateMessage>,
@@ -80,7 +80,7 @@ impl Pending {
impl<Fs: FileStore> ClientLogic<Fs> {
pub fn new(
client: Client<Fs>,
- bare_jid: JID,
+ jid: BareJID,
db: Db,
update_sender: mpsc::Sender<UpdateMessage>,
file_store: Fs,
@@ -90,7 +90,7 @@ impl<Fs: FileStore> ClientLogic<Fs> {
pending: Pending::new(),
update_sender,
client,
- bare_jid,
+ jid,
file_store,
}
}
diff --git a/filamento/src/logic/offline.rs b/filamento/src/logic/offline.rs
index 606b04f..aa84f3d 100644
--- a/filamento/src/logic/offline.rs
+++ b/filamento/src/logic/offline.rs
@@ -1,6 +1,7 @@
use std::process::id;
use chrono::Utc;
+use jid::FullJID;
use lampada::error::WriteError;
use tracing::error;
use uuid::Uuid;
@@ -19,9 +20,13 @@ use crate::{
};
use super::{
+ ClientLogic,
local_only::{
- handle_delete_chat, handle_delete_messaage, handle_get_chat, handle_get_chat_and_user, handle_get_chats, handle_get_chats_ordered, handle_get_chats_ordered_with_latest_messages, handle_get_chats_ordered_with_latest_messages_and_users, handle_get_message, handle_get_messages, handle_get_messages_with_users, handle_get_user
- }, ClientLogic
+ handle_delete_chat, handle_delete_messaage, handle_get_chat, handle_get_chat_and_user,
+ handle_get_chats, handle_get_chats_ordered, handle_get_chats_ordered_with_latest_messages,
+ handle_get_chats_ordered_with_latest_messages_and_users, handle_get_message,
+ handle_get_messages, handle_get_messages_with_users, handle_get_user,
+ },
};
pub async fn handle_offline<Fs: FileStore + Clone>(logic: ClientLogic<Fs>, command: Command<Fs>) {
@@ -153,7 +158,7 @@ pub async fn handle_offline_result<Fs: FileStore + Clone>(
let message = Message {
id,
- from: logic.bare_jid.clone(),
+ from: logic.jid.clone(),
// TODO: failure reason
delivery: Some(Delivery::Failed),
timestamp,
@@ -163,11 +168,15 @@ pub async fn handle_offline_result<Fs: FileStore + Clone>(
// TODO: mark these as potentially failed upon client launch
if let Err(e) = logic
.db()
+ // TODO: can create message without a resource....
.create_message_with_user_resource(
message.clone(),
jid.clone(),
// TODO: when message is queued and sent, the from must also be updated with the correct resource
- logic.bare_jid.clone(),
+ FullJID {
+ bare_jid: logic.jid.clone(),
+ resourcepart: "unsent".to_string(),
+ },
)
.await
{
@@ -177,12 +186,12 @@ pub async fn handle_offline_result<Fs: FileStore + Clone>(
.await;
}
- let from = match logic.db().read_user(logic.bare_jid.clone()).await {
+ let from = match logic.db().read_user(logic.jid.clone()).await {
Ok(u) => u,
Err(e) => {
error!("{}", e);
User {
- jid: logic.bare_jid.clone(),
+ jid: logic.jid.clone(),
nick: None,
avatar: None,
}
@@ -192,7 +201,7 @@ pub async fn handle_offline_result<Fs: FileStore + Clone>(
logic
.update_sender()
.send(crate::UpdateMessage::Message {
- to: jid.as_bare(),
+ to: jid,
message,
from,
})
diff --git a/filamento/src/logic/online.rs b/filamento/src/logic/online.rs
index 9814ff2..febd3e1 100644
--- a/filamento/src/logic/online.rs
+++ b/filamento/src/logic/online.rs
@@ -3,7 +3,7 @@ use std::{io::Cursor, time::Duration};
use base64::{prelude::BASE64_STANDARD, Engine};
use chrono::Utc;
use image::ImageReader;
-use jid::JID;
+use jid::{BareJID, JID};
use lampada::{Connected, WriteMessage, error::WriteError};
use sha1::{Digest, Sha1};
use stanza::{
@@ -41,7 +41,7 @@ pub async fn handle_get_roster<Fs: FileStore + Clone>(
) -> Result<Vec<Contact>, RosterError> {
let iq_id = Uuid::new_v4().to_string();
let stanza = Stanza::Iq(Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq_id.to_string(),
to: None,
r#type: IqType::Get,
@@ -101,7 +101,7 @@ pub async fn handle_get_roster_with_users<Fs: FileStore + Clone>(
) -> Result<Vec<(Contact, User)>, RosterError> {
let iq_id = Uuid::new_v4().to_string();
let stanza = Stanza::Iq(Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq_id.to_string(),
to: None,
r#type: IqType::Get,
@@ -162,11 +162,11 @@ pub async fn handle_get_roster_with_users<Fs: FileStore + Clone>(
pub async fn handle_add_contact<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
connection: Connected,
- jid: JID,
+ jid: BareJID,
) -> Result<(), RosterError> {
let iq_id = Uuid::new_v4().to_string();
let set_stanza = Stanza::Iq(Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq_id.clone(),
to: None,
r#type: IqType::Set,
@@ -220,9 +220,10 @@ pub async fn handle_add_contact<Fs: FileStore + Clone>(
pub async fn handle_buddy_request<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
connection: Connected,
- jid: JID,
+ jid: BareJID,
) -> Result<(), SubscribeError> {
- let client_user = logic.db.read_user(logic.bare_jid.clone()).await?;
+ let jid: JID = jid.into();
+ let client_user = logic.db.read_user(logic.jid.clone()).await?;
let nick = client_user.nick.map(|nick| Nick(nick));
let presence = Stanza::Presence(stanza::client::presence::Presence {
to: Some(jid.clone()),
@@ -243,13 +244,13 @@ pub async fn handle_buddy_request<Fs: FileStore + Clone>(
pub async fn handle_subscription_request<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
connection: Connected,
- jid: JID,
+ jid: BareJID,
) -> Result<(), SubscribeError> {
// TODO: i should probably have builders
- let client_user = logic.db.read_user(logic.bare_jid.clone()).await?;
+ let client_user = logic.db.read_user(logic.jid.clone()).await?;
let nick = client_user.nick.map(|nick| Nick(nick));
let presence = Stanza::Presence(stanza::client::presence::Presence {
- to: Some(jid),
+ to: Some(jid.into()),
r#type: Some(stanza::client::presence::PresenceType::Subscribe),
nick,
..Default::default()
@@ -261,15 +262,16 @@ pub async fn handle_subscription_request<Fs: FileStore + Clone>(
pub async fn handle_accept_buddy_request<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
connection: Connected,
- jid: JID,
+ jid: BareJID,
) -> Result<(), SubscribeError> {
+ let jid: JID = jid.into();
let presence = Stanza::Presence(stanza::client::presence::Presence {
to: Some(jid.clone()),
r#type: Some(stanza::client::presence::PresenceType::Subscribed),
..Default::default()
});
connection.write_handle().write(presence).await?;
- let client_user = logic.db.read_user(logic.bare_jid.clone()).await?;
+ let client_user = logic.db.read_user(logic.jid.clone()).await?;
let nick = client_user.nick.map(|nick| Nick(nick));
let presence = Stanza::Presence(stanza::client::presence::Presence {
to: Some(jid),
@@ -284,12 +286,12 @@ pub async fn handle_accept_buddy_request<Fs: FileStore + Clone>(
pub async fn handle_accept_subscription_request<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
connection: Connected,
- jid: JID,
+ jid: BareJID,
) -> Result<(), SubscribeError> {
- let client_user = logic.db.read_user(logic.bare_jid.clone()).await?;
+ let client_user = logic.db.read_user(logic.jid.clone()).await?;
let nick = client_user.nick.map(|nick| Nick(nick));
let presence = Stanza::Presence(stanza::client::presence::Presence {
- to: Some(jid),
+ to: Some(jid.into()),
r#type: Some(stanza::client::presence::PresenceType::Subscribe),
nick,
..Default::default()
@@ -300,10 +302,10 @@ pub async fn handle_accept_subscription_request<Fs: FileStore + Clone>(
pub async fn handle_unsubscribe_from_contact(
connection: Connected,
- jid: JID,
+ jid: BareJID,
) -> Result<(), WriteError> {
let presence = Stanza::Presence(stanza::client::presence::Presence {
- to: Some(jid),
+ to: Some(jid.into()),
r#type: Some(stanza::client::presence::PresenceType::Unsubscribe),
..Default::default()
});
@@ -311,9 +313,9 @@ pub async fn handle_unsubscribe_from_contact(
Ok(())
}
-pub async fn handle_unsubscribe_contact(connection: Connected, jid: JID) -> Result<(), WriteError> {
+pub async fn handle_unsubscribe_contact(connection: Connected, jid: BareJID) -> Result<(), WriteError> {
let presence = Stanza::Presence(stanza::client::presence::Presence {
- to: Some(jid),
+ to: Some(jid.into()),
r#type: Some(stanza::client::presence::PresenceType::Unsubscribed),
..Default::default()
});
@@ -321,7 +323,8 @@ pub async fn handle_unsubscribe_contact(connection: Connected, jid: JID) -> Resu
Ok(())
}
-pub async fn handle_unfriend_contact(connection: Connected, jid: JID) -> Result<(), WriteError> {
+pub async fn handle_unfriend_contact(connection: Connected, jid: BareJID) -> Result<(), WriteError> {
+ let jid: JID = jid.into();
let presence = Stanza::Presence(stanza::client::presence::Presence {
to: Some(jid.clone()),
r#type: Some(stanza::client::presence::PresenceType::Unsubscribe),
@@ -340,11 +343,11 @@ pub async fn handle_unfriend_contact(connection: Connected, jid: JID) -> Result<
pub async fn handle_delete_contact<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
connection: Connected,
- jid: JID,
+ jid: BareJID,
) -> Result<(), RosterError> {
let iq_id = Uuid::new_v4().to_string();
let set_stanza = Stanza::Iq(Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq_id.clone(),
to: None,
r#type: IqType::Set,
@@ -399,7 +402,7 @@ pub async fn handle_delete_contact<Fs: FileStore + Clone>(
pub async fn handle_update_contact<Fs: FileStore + Clone>(
logic: &ClientLogic<Fs>,
connection: Connected,
- jid: JID,
+ jid: BareJID,
contact_update: ContactUpdate,
) -> Result<(), RosterError> {
let iq_id = Uuid::new_v4().to_string();
@@ -410,7 +413,8 @@ pub async fn handle_update_contact<Fs: FileStore + Clone>(
.map(|group| stanza::roster::Group(Some(group))),
);
let set_stanza = Stanza::Iq(Iq {
- from: Some(connection.jid().clone()),
+ // TODO: these clones could technically be avoided?
+ from: Some(connection.jid().clone().into()),
id: iq_id.clone(),
to: None,
r#type: IqType::Set,
@@ -474,7 +478,7 @@ pub async fn handle_set_status<Fs: FileStore + Clone>(
Ok(())
}
-pub async fn handle_send_message<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>, connection: Connected, jid: JID, body: Body) {
+pub async fn handle_send_message<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>, connection: Connected, jid: BareJID, body: Body) {
// upsert the chat and user the message will be delivered to. if there is a conflict, it will return whatever was there, otherwise it will return false by default.
// let have_chatted = logic.db().upsert_chat_and_user(&jid).await.unwrap_or(false);
let have_chatted = match logic.db().upsert_chat_and_user(jid.clone()).await {
@@ -490,7 +494,7 @@ pub async fn handle_send_message<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>,
let nick;
let mark_chat_as_chatted;
if have_chatted == false {
- match logic.db.read_user(logic.bare_jid.clone()).await {
+ match logic.db.read_user(logic.jid.clone()).await {
Ok(u) => {
nick = u.nick.map(|nick| Nick(nick));
mark_chat_as_chatted = true;
@@ -513,7 +517,7 @@ pub async fn handle_send_message<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>,
let timestamp = Utc::now();
let message = Message {
id,
- from: connection.jid().as_bare(),
+ from: connection.jid().to_bare(),
body: body.clone(),
timestamp,
delivery: Some(Delivery::Sending),
@@ -532,12 +536,12 @@ pub async fn handle_send_message<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>,
.await;
}
- let from = match logic.db().read_user(logic.bare_jid.clone()).await {
+ let from = match logic.db().read_user(logic.jid.clone()).await {
Ok(u) => u,
Err(e) => {
error!("{}", e);
User {
- jid: logic.bare_jid.clone(),
+ jid: logic.jid.clone(),
nick: None,
avatar: None,
}
@@ -548,7 +552,7 @@ pub async fn handle_send_message<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>,
logic
.update_sender()
.send(UpdateMessage::Message {
- to: jid.as_bare(),
+ to: jid.clone(),
message,
from,
})
@@ -556,9 +560,9 @@ pub async fn handle_send_message<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>,
// prepare the message stanza
let message_stanza = Stanza::Message(stanza::client::message::Message {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: Some(id.to_string()),
- to: Some(jid.clone()),
+ to: Some(jid.clone().into()),
// TODO: specify message type
r#type: stanza::client::message::MessageType::Chat,
// TODO: lang ?
@@ -639,7 +643,7 @@ pub async fn handle_disco_info<Fs: FileStore + Clone>(
) -> Result<Info, DiscoError> {
let id = Uuid::new_v4().to_string();
let request = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: id.clone(),
to: jid.clone(),
r#type: IqType::Get,
@@ -667,7 +671,7 @@ pub async fn handle_disco_info<Fs: FileStore + Clone>(
}) if r#type == IqType::Result || r#type == IqType::Error => {
if from == jid || {
if jid == None {
- from == Some(connection.jid().as_bare())
+ from == Some(connection.jid().to_bare().into())
} else {
false
}
@@ -694,7 +698,7 @@ pub async fn handle_disco_info<Fs: FileStore + Clone>(
}
} else {
Err(DiscoError::IncorrectEntity(
- from.unwrap_or_else(|| connection.jid().as_bare()),
+ from.unwrap_or_else(|| connection.jid().to_bare().into()),
))
}
}
@@ -710,7 +714,7 @@ pub async fn handle_disco_items<Fs: FileStore + Clone>(
) -> Result<Items, DiscoError> {
let id = Uuid::new_v4().to_string();
let request = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: id.clone(),
to: jid.clone(),
r#type: IqType::Get,
@@ -736,7 +740,7 @@ pub async fn handle_disco_items<Fs: FileStore + Clone>(
}) if r#type == IqType::Result || r#type == IqType::Error => {
if from == jid || {
if jid == None {
- from == Some(connection.jid().as_bare())
+ from == Some(connection.jid().to_bare().into())
} else {
false
}
@@ -763,7 +767,7 @@ pub async fn handle_disco_items<Fs: FileStore + Clone>(
}
} else {
Err(DiscoError::IncorrectEntity(
- from.unwrap_or_else(|| connection.jid().as_bare()),
+ from.unwrap_or_else(|| connection.jid().to_bare().into()),
))
}
}
@@ -828,7 +832,7 @@ pub async fn handle_publish_pep_item<Fs: FileStore + Clone>(
},
};
let request = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: id.clone(),
to: None,
r#type: IqType::Set,
@@ -850,7 +854,7 @@ pub async fn handle_publish_pep_item<Fs: FileStore + Clone>(
// TODO: maybe abstract a bunch of these different errors related to iqs into an iq error thing? as in like call iq.result(), get the query from inside, error otherwise.
}) if r#type == IqType::Result || r#type == IqType::Error => {
if from == None ||
- from == Some(connection.jid().as_bare())
+ from == Some(connection.jid().to_bare().into())
{
match r#type {
IqType::Result => {
@@ -870,7 +874,7 @@ pub async fn handle_publish_pep_item<Fs: FileStore + Clone>(
}
} else {
Err(PEPError::IncorrectEntity(
- from.unwrap_or_else(|| connection.jid().as_bare()),
+ from.unwrap_or_else(|| connection.jid().to_bare().into()),
))
}
}
@@ -878,10 +882,11 @@ pub async fn handle_publish_pep_item<Fs: FileStore + Clone>(
}
}
-pub async fn handle_get_pep_item<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>, connection: Connected, jid: Option<JID>, node: String, id: String) -> Result<pep::Item, PEPError> {
+pub async fn handle_get_pep_item<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>, connection: Connected, jid: Option<BareJID>, node: String, id: String) -> Result<pep::Item, PEPError> {
+ let jid = jid.map(|jid| Into::<JID>::into(jid));
let stanza_id = Uuid::new_v4().to_string();
let request = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: stanza_id.clone(),
to: jid.clone(),
r#type: IqType::Get,
@@ -909,7 +914,7 @@ pub async fn handle_get_pep_item<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>,
}) if r#type == IqType::Result || r#type == IqType::Error => {
if from == jid || {
if jid == None {
- from == Some(connection.jid().as_bare())
+ from == Some(connection.jid().to_bare().into())
} else {
false
}
@@ -955,7 +960,7 @@ pub async fn handle_get_pep_item<Fs: FileStore + Clone>(logic: &ClientLogic<Fs>,
} else {
// TODO: include expected entity
Err(PEPError::IncorrectEntity(
- from.unwrap_or_else(|| connection.jid().as_bare()),
+ from.unwrap_or_else(|| connection.jid().to_bare().into()),
))
}
}
@@ -1024,7 +1029,7 @@ pub async fn handle_delete_pep_node<Fs: FileStore + Clone>(
) -> Result<(), PEPError> {
let id = Uuid::new_v4().to_string();
let request = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: id.clone(),
to: None,
r#type: IqType::Set,
@@ -1046,7 +1051,7 @@ pub async fn handle_delete_pep_node<Fs: FileStore + Clone>(
// TODO: maybe abstract a bunch of these different errors related to iqs into an iq error thing? as in like call iq.result(), get the query from inside, error otherwise.
}) if r#type == IqType::Result || r#type == IqType::Error => {
if from == None ||
- from == Some(connection.jid().as_bare())
+ from == Some(connection.jid().to_bare().into())
{
match r#type {
IqType::Result => {
@@ -1067,7 +1072,7 @@ pub async fn handle_delete_pep_node<Fs: FileStore + Clone>(
}
} else {
Err(PEPError::IncorrectEntity(
- from.unwrap_or_else(|| connection.jid().as_bare()),
+ from.unwrap_or_else(|| connection.jid().to_bare().into()),
))
}
}
diff --git a/filamento/src/logic/process_stanza.rs b/filamento/src/logic/process_stanza.rs
index 30d0830..67b0d3f 100644
--- a/filamento/src/logic/process_stanza.rs
+++ b/filamento/src/logic/process_stanza.rs
@@ -70,7 +70,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
// TODO: proper id xep
.map(|id| Uuid::from_str(&id).unwrap_or_else(|_| Uuid::new_v4()))
.unwrap_or_else(|| Uuid::new_v4()),
- from: from.as_bare(),
+ from: from.to_bare(),
timestamp,
body: Body {
body: body.body.unwrap_or_default(),
@@ -80,31 +80,34 @@ pub async fn recv_message<Fs: FileStore + Clone>(
// TODO: process message type="error"
// save the message to the database
- match logic.db().upsert_chat_and_user(from.clone()).await {
- Ok(_) => {
- if let Err(e) = logic
- .db()
- .create_message_with_user_resource(
- message.clone(),
- from.clone(),
- from.clone(),
- )
- .await
- {
- error!("failed to create message: {}", e);
+ match logic.db().upsert_chat_and_user(from.to_bare()).await {
+ Ok(_) => match from.as_full() {
+ Ok(from) => {
+ if let Err(e) = logic
+ .db()
+ .create_message_with_user_resource(
+ message.clone(),
+ from.to_bare(),
+ from.clone(),
+ )
+ .await
+ {
+ error!("failed to create message: {}", e);
+ }
}
- }
+ Err(e) => error!("failed to create message: {}", e),
+ },
Err(e) => {
error!("failed to upsert chat and user: {}", e);
}
};
- let from_user = match logic.db().read_user(from.as_bare()).await {
+ let from_user = match logic.db().read_user(from.to_bare()).await {
Ok(u) => u,
Err(e) => {
error!("{}", e);
User {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: None,
avatar: None,
}
@@ -115,7 +118,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::Message {
- to: from.as_bare(),
+ to: from.to_bare(),
from: from_user,
message,
})
@@ -125,13 +128,13 @@ pub async fn recv_message<Fs: FileStore + Clone>(
if let Some(nick) = stanza_message.nick {
let nick = nick.0;
if nick.is_empty() {
- match logic.db().delete_user_nick(from.as_bare()).await {
+ match logic.db().delete_user_nick(from.to_bare()).await {
Ok(changed) => {
if changed {
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: None,
})
.await;
@@ -145,7 +148,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: None,
})
.await;
@@ -154,7 +157,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
} else {
match logic
.db()
- .upsert_user_nick(from.as_bare(), nick.clone())
+ .upsert_user_nick(from.to_bare(), nick.clone())
.await
{
Ok(changed) => {
@@ -162,7 +165,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: Some(nick),
})
.await;
@@ -176,7 +179,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: Some(nick),
})
.await;
@@ -199,7 +202,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
if nick.is_empty() {
match logic
.db()
- .delete_user_nick(from.as_bare())
+ .delete_user_nick(from.to_bare())
.await
{
Ok(changed) => {
@@ -207,7 +210,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: None,
})
.await;
@@ -223,7 +226,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: None,
})
.await;
@@ -233,7 +236,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
match logic
.db()
.upsert_user_nick(
- from.as_bare(),
+ from.to_bare(),
nick.clone(),
)
.await
@@ -243,7 +246,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: Some(nick),
})
.await;
@@ -259,7 +262,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
logic
.update_sender()
.send(UpdateMessage::NickChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
nick: Some(nick),
})
.await;
@@ -294,7 +297,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
match logic
.db()
.upsert_user_avatar(
- from.as_bare(),
+ from.to_bare(),
metadata.id.clone(),
)
.await
@@ -323,7 +326,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
}) {
Ok(false) => {
// get data
- let pep_item = logic.client().get_pep_item(Some(from.as_bare()), "urn:xmpp:avatar:data".to_string(), metadata.id.clone()).await.map_err(|err| Into::<AvatarUpdateError<Fs>>::into(err))?;
+ let pep_item = logic.client().get_pep_item(Some(from.to_bare()), "urn:xmpp:avatar:data".to_string(), metadata.id.clone()).await.map_err(|err| Into::<AvatarUpdateError<Fs>>::into(err))?;
match pep_item {
crate::pep::Item::AvatarData(data) => {
let data = data.map(|data| data.data_b64).unwrap_or_default().replace("\n", "");
@@ -344,7 +347,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
.update_sender()
.send(
UpdateMessage::AvatarChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
id: Some(
metadata.id.clone(),
),
@@ -371,7 +374,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
.update_sender()
.send(
UpdateMessage::AvatarChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
id: Some(
metadata.id.clone(),
),
@@ -401,7 +404,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
// delete avatar
match logic
.db()
- .delete_user_avatar(from.as_bare())
+ .delete_user_avatar(from.to_bare())
.await
{
Ok((changed, old_avatar)) => {
@@ -419,7 +422,7 @@ pub async fn recv_message<Fs: FileStore + Clone>(
.update_sender()
.send(
UpdateMessage::AvatarChanged {
- jid: from.as_bare(),
+ jid: from.to_bare(),
id: None,
},
)
@@ -488,6 +491,7 @@ pub async fn recv_presence(
}
stanza::client::presence::PresenceType::Subscribe => {
// may get a subscription request from somebody who is not a contact!!! therefore should be its own kind of event
+ let from = from.try_into()?;
Ok(Some(UpdateMessage::SubscriptionRequest(from)))
}
stanza::client::presence::PresenceType::Unavailable => {
@@ -546,7 +550,8 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
iq: Iq,
) -> Result<Option<UpdateMessage>, IqProcessError> {
if let Some(to) = &iq.to {
- if *to == *connection.jid() {
+ // TODO: this clone could mayb b avoided
+ if *to == connection.jid().clone().into() {
} else {
return Err(IqProcessError::Iq(IqError::IncorrectAddressee(to.clone())));
}
@@ -556,7 +561,9 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
let from = iq
.from
.clone()
- .unwrap_or_else(|| connection.server().clone());
+ // TODO: maybe actually store the server in the connection again LOL
+ // .unwrap_or_else(|| connection.server().clone());
+ .unwrap_or_else(|| connection.jid().domainpart.parse().unwrap());
let id = iq.id.clone();
debug!("received iq result with id `{}` from {}", id, from);
logic
@@ -570,7 +577,8 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
let from = iq
.from
.clone()
- .unwrap_or_else(|| connection.server().clone());
+ // .unwrap_or_else(|| connection.server().clone());
+ .unwrap_or_else(|| connection.jid().domainpart.parse().unwrap());
if let Some(query) = iq.query {
match query {
stanza::client::iq::Query::DiscoInfo(query) => {
@@ -594,7 +602,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
}
Err(_e) => {
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Error,
@@ -614,7 +622,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
},
Err(_e) => {
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Error,
@@ -634,7 +642,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
}
};
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Result,
@@ -653,7 +661,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
_ => {
warn!("received unsupported iq get from {}", from);
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Error,
@@ -677,7 +685,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
} else {
info!("received malformed iq query from {}", from);
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Error,
@@ -698,7 +706,8 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
let from = iq
.from
.clone()
- .unwrap_or_else(|| connection.server().clone());
+ // .unwrap_or_else(|| connection.server().clone());
+ .unwrap_or_else(|| connection.jid().domainpart.parse().unwrap());
if let Some(query) = iq.query {
match query {
stanza::client::iq::Query::Roster(mut query) => {
@@ -725,7 +734,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
.await;
}
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Result,
@@ -751,7 +760,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
} else {
warn!("received malformed roster push");
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Error,
@@ -771,7 +780,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
_ => {
warn!("received unsupported iq set from {}", from);
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Error,
@@ -791,7 +800,7 @@ pub async fn recv_iq<Fs: FileStore + Clone>(
} else {
warn!("received malformed iq set from {}", from);
let iq = Iq {
- from: Some(connection.jid().clone()),
+ from: Some(connection.jid().clone().into()),
id: iq.id,
to: iq.from,
r#type: IqType::Error,
@@ -820,7 +829,7 @@ pub async fn process_stanza<Fs: FileStore + Clone>(
Stanza::Presence(presence) => Ok(recv_presence(presence).await?),
Stanza::Iq(iq) => Ok(recv_iq(logic, connection.clone(), iq).await?),
// unreachable, always caught by lampada
- // TODO: make cleaner than this in some way
+ // TODO: make cleaner than this in some way, by just reexporting a stanza enum from lampada ig.
Stanza::Error(error) => {
unreachable!()
}
diff --git a/filamento/src/roster.rs b/filamento/src/roster.rs
index 6b61e10..0498278 100644
--- a/filamento/src/roster.rs
+++ b/filamento/src/roster.rs
@@ -1,6 +1,6 @@
use std::{collections::HashSet, fmt::Display};
-use jid::JID;
+use jid::BareJID;
use rusqlite::{
ToSql,
types::{FromSql, ToSqlOutput, Value},
@@ -15,7 +15,7 @@ pub struct ContactUpdate {
#[cfg_attr(feature = "reactive_stores", derive(reactive_stores::Store))]
pub struct Contact {
// jid is the id used to reference everything, but not the primary key
- pub user_jid: JID,
+ pub user_jid: BareJID,
pub subscription: Subscription,
/// client user defined name
pub name: Option<String>,
diff --git a/filamento/src/user.rs b/filamento/src/user.rs
index f30933c..f962a4c 100644
--- a/filamento/src/user.rs
+++ b/filamento/src/user.rs
@@ -1,10 +1,10 @@
-use jid::JID;
+use jid::BareJID;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
#[cfg_attr(feature = "reactive_stores", derive(reactive_stores::Store))]
pub struct User {
- pub jid: JID,
+ pub jid: BareJID,
pub nick: Option<String>,
pub avatar: Option<String>,
// pub cached_status_message: Option<String>,
diff --git a/lampada/src/connection/mod.rs b/lampada/src/connection/mod.rs
index 3a3187f..51c3758 100644
--- a/lampada/src/connection/mod.rs
+++ b/lampada/src/connection/mod.rs
@@ -7,7 +7,7 @@ use std::{
time::Duration,
};
-use jid::JID;
+use jid::{BareJID, FullJID, JID};
use luz::jabber_stream::bound_stream::BoundJabberStream;
use read::{ReadControl, ReadControlHandle, ReadState};
use stanza::{client::Stanza, stream_error::Error as StreamError};
@@ -121,12 +121,11 @@ where
break
}
- let mut jid = self.connected.jid.clone();
- let mut domain = jid.domainpart.clone();
+ let mut jid = self.connected.jid.clone().into();
// TODO: make sure connect_and_login does not modify the jid, but instead returns a jid. or something like that
- let connection = luz::connect_and_login(&mut jid, &*self.password, &mut domain).await;
+ let connection = luz::connect_and_login(&jid, &*self.password).await;
match connection {
- Ok(c) => {
+ Ok((c, full_jid)) => {
let (read, write) = c.split();
let (send, recv) = oneshot::channel();
self.writer_crash = recv;
@@ -169,12 +168,11 @@ where
else => break,
};
- let mut jid = self.connected.jid.clone();
- let mut domain = jid.domainpart.clone();
+ let mut jid = self.connected.jid.clone().into();
// TODO: same here
- let connection = luz::connect_and_login(&mut jid, &*self.password, &mut domain).await;
+ let connection = luz::connect_and_login(&jid, &*self.password).await;
match connection {
- Ok(c) => {
+ Ok((c, full_jid)) => {
let (read, write) = c.split();
let (send, recv) = oneshot::channel();
self.writer_crash = recv;
@@ -214,11 +212,10 @@ where
else => break,
};
- let mut jid = self.connected.jid.clone();
- let mut domain = jid.domainpart.clone();
- let connection = luz::connect_and_login(&mut jid, &*self.password, &mut domain).await;
+ let mut jid = self.connected.jid.clone().into();
+ let connection = luz::connect_and_login(&jid, &*self.password).await;
match connection {
- Ok(c) => {
+ Ok((c, full_jid)) => {
let (read, write) = c.split();
let (send, recv) = oneshot::channel();
self.writer_crash = recv;
@@ -305,8 +302,7 @@ impl SupervisorHandle {
pub fn new<Lgc>(
streams: BoundJabberStream,
on_crash: oneshot::Sender<()>,
- jid: JID,
- server: JID,
+ jid: FullJID,
password: Arc<String>,
logic: Lgc,
) -> (WriteHandle, Self)
@@ -327,7 +323,6 @@ impl SupervisorHandle {
let connected = Connected {
jid,
write_handle: write_handle.clone(),
- server,
};
let supervisor_sender = SupervisorSender {
diff --git a/lampada/src/error.rs b/lampada/src/error.rs
index f29d0cc..a5af3a2 100644
--- a/lampada/src/error.rs
+++ b/lampada/src/error.rs
@@ -24,7 +24,7 @@ pub enum ConnectionError {
#[error("disconnected")]
Disconnected,
#[error("invalid server jid: {0}")]
- InvalidServerJID(#[from] jid::ParseError),
+ InvalidServerJID(#[from] jid::JIDError),
}
#[derive(Debug, Error, Clone)]
diff --git a/lampada/src/lib.rs b/lampada/src/lib.rs
index 6b6cbe8..d1d451e 100644
--- a/lampada/src/lib.rs
+++ b/lampada/src/lib.rs
@@ -12,6 +12,7 @@ pub use connection::write::WriteMessage;
pub use connection::SupervisorSender;
use error::ConnectionError;
use futures::{future::Fuse, FutureExt};
+use jid::{BareJID, FullJID};
use luz::JID;
use stanza::client::{
iq::{self, Iq, IqType},
@@ -36,24 +37,18 @@ pub mod error;
#[derive(Clone)]
pub struct Connected {
// full jid will stay stable across reconnections
- jid: JID,
+ jid: FullJID,
write_handle: WriteHandle,
- // the server jid
- server: JID,
}
impl Connected {
- pub fn jid(&self) -> &JID {
+ pub fn jid(&self) -> &FullJID {
&self.jid
}
pub fn write_handle(&self) -> &WriteHandle {
&self.write_handle
}
-
- pub fn server(&self) -> &JID {
- &self.server
- }
}
/// everything that a particular xmpp client must implement
@@ -227,34 +222,17 @@ where
.await;
}
None => {
- let mut jid = self.jid.clone();
- let mut domain = jid.domainpart.clone();
// TODO: check what happens upon reconnection with same resource (this is probably what one wants to do and why jid should be mutated from a bare jid to one with a resource)
let streams_result =
- luz::connect_and_login(&mut jid, &*self.password, &mut domain)
- .await;
- let server: JID = match domain.parse() {
- Ok(j) => j,
- Err(e) => {
- self.logic
- .clone()
- .handle_connection_error(ConnectionError::InvalidServerJID(
- e.clone(),
- ))
- .await;
- sender.send(Err(ConnectionError::InvalidServerJID(e)));
- continue;
- }
- };
+ luz::connect_and_login(&self.jid, &*self.password).await;
match streams_result {
- Ok(s) => {
+ Ok((s, full_jid)) => {
debug!("ok stream result");
let (shutdown_send, shutdown_recv) = oneshot::channel::<()>();
let (writer, supervisor) = SupervisorHandle::new(
s,
shutdown_send,
- jid.clone(),
- server.clone(),
+ full_jid.clone(),
self.password.clone(),
self.logic.clone(),
);
@@ -262,18 +240,16 @@ where
let shutdown_recv = shutdown_recv.fuse();
self.connection_supervisor_shutdown = shutdown_recv;
- let resource = jid.resourcepart.clone().expect("client somehow connected without binding");
let connected = Connected {
- jid,
+ jid: full_jid.clone(),
write_handle: writer,
- server,
};
self.logic.clone().handle_connect(connected.clone()).await;
self.connected = Some((connected, supervisor));
// REMEMBER TO NOTIFY IT@S GOOD
- sender.send(Ok(resource));
+ sender.send(Ok(full_jid.resourcepart));
}
Err(e) => {
tracing::error!("error: {}", e);
diff --git a/luz/src/client/tcp.rs b/luz/src/client/tcp.rs
index 4e35ef0..a30eccc 100644
--- a/luz/src/client/tcp.rs
+++ b/luz/src/client/tcp.rs
@@ -1,3 +1,4 @@
+use jid::FullJID;
use rsasl::config::SASLConfig;
use stanza::{
sasl::Mechanisms,
@@ -10,22 +11,25 @@ use crate::{
};
pub async fn connect_and_login(
- jid: &mut JID,
+ jid: &JID,
+ // jid: &mut JID,
password: impl AsRef<str>,
- server: &mut String,
-) -> Result<BoundJabberStream> {
+ // server: &mut String,
+) -> Result<(BoundJabberStream, FullJID)> {
let auth = SASLConfig::with_credentials(
None,
jid.localpart.clone().ok_or(Error::NoLocalpart)?,
password.as_ref().to_string(),
)
.map_err(|e| Error::SASL(e.into()))?;
+ let mut server = jid.domainpart.clone();
let mut conn_state = Connecting::start(&server).await?;
loop {
match conn_state {
Connecting::InsecureConnectionEstablised(tcp_stream) => {
conn_state = Connecting::InsecureStreamStarted(
- JabberStream::start_stream(Connection::Unencrypted(tcp_stream), server).await?,
+ JabberStream::start_stream(Connection::Unencrypted(tcp_stream), &mut server)
+ .await?,
)
}
Connecting::InsecureStreamStarted(jabber_stream) => {
@@ -46,8 +50,9 @@ pub async fn connect_and_login(
))
}
Connecting::ConnectionEstablished(connection) => {
- conn_state =
- Connecting::StreamStarted(JabberStream::start_stream(connection, server).await?)
+ conn_state = Connecting::StreamStarted(
+ JabberStream::start_stream(connection, &mut server).await?,
+ )
}
Connecting::StreamStarted(jabber_stream) => {
conn_state = Connecting::GotFeatures(jabber_stream.get_features().await?)
@@ -68,7 +73,7 @@ pub async fn connect_and_login(
)
}
Connecting::Bind(jabber_stream) => {
- return Ok(jabber_stream.bind(jid).await?.to_bound_jabber());
+ return Ok(jabber_stream.bind(jid).await?);
}
}
}
diff --git a/luz/src/client/ws.rs b/luz/src/client/ws.rs
index 13c3cdf..0ad8d0e 100644
--- a/luz/src/client/ws.rs
+++ b/luz/src/client/ws.rs
@@ -1,3 +1,4 @@
+use jid::FullJID;
use rsasl::config::SASLConfig;
use stanza::{
sasl::Mechanisms,
@@ -9,22 +10,22 @@ use crate::{
};
pub async fn connect_and_login(
- jid: &mut JID,
+ jid: &JID,
password: impl AsRef<str>,
- server: &mut String,
-) -> Result<BoundJabberStream> {
+) -> Result<(BoundJabberStream, FullJID)> {
let auth = SASLConfig::with_credentials(
None,
jid.localpart.clone().ok_or(Error::NoLocalpart)?,
password.as_ref().to_string(),
)
.map_err(|e| Error::SASL(e.into()))?;
+ let mut server = jid.domainpart.clone();
let mut conn_state = Connecting::start(&server).await?;
loop {
match conn_state {
Connecting::ConnectionEstablished(ws) => {
conn_state =
- Connecting::StreamStarted(JabberStream::start_stream(ws, server).await?)
+ Connecting::StreamStarted(JabberStream::start_stream(ws, &mut server).await?)
}
Connecting::StreamStarted(jabber_stream) => {
conn_state = Connecting::GotFeatures(jabber_stream.get_features().await?)
@@ -45,7 +46,7 @@ pub async fn connect_and_login(
)
}
Connecting::Bind(jabber_stream) => {
- return Ok(jabber_stream.bind(jid).await?.to_bound_jabber());
+ return Ok(jabber_stream.bind(jid).await?);
}
}
}
diff --git a/luz/src/connection/tcp.rs b/luz/src/connection/tcp.rs
index a9e81c3..7409a47 100644
--- a/luz/src/connection/tcp.rs
+++ b/luz/src/connection/tcp.rs
@@ -96,7 +96,7 @@ impl Connection {
// }
pub async fn connect_user(jid: impl AsRef<str>) -> Result<Self> {
- let jid: JID = JID::from_str(jid.as_ref())?;
+ let jid: JID = JID::from_str(jid.as_ref()).map_err(|e| Error::JID(e.into()))?;
let server = jid.domainpart.clone();
Self::connect(&server).await
}
diff --git a/luz/src/error.rs b/luz/src/error.rs
index fcb32a0..d9b2930 100644
--- a/luz/src/error.rs
+++ b/luz/src/error.rs
@@ -1,7 +1,7 @@
use std::str::Utf8Error;
use std::sync::Arc;
-use jid::ParseError;
+use jid::JIDError;
use rsasl::mechname::MechanismNameError;
use stanza::client::error::Error as ClientError;
use stanza::sasl::Failure;
@@ -36,7 +36,7 @@ pub enum Error {
#[error("sasl error: {0}")]
SASL(#[from] SASLError),
#[error("jid error: {0}")]
- JID(#[from] ParseError),
+ JID(#[from] JIDError),
#[error("client stanza error: {0}")]
ClientError(#[from] ClientError),
#[error("stream error: {0}")]
diff --git a/luz/src/jabber_stream.rs b/luz/src/jabber_stream.rs
index f77e6a9..490a0f7 100644
--- a/luz/src/jabber_stream.rs
+++ b/luz/src/jabber_stream.rs
@@ -7,7 +7,8 @@ mod ws;
use std::str::{self, FromStr};
use std::sync::Arc;
-use jid::JID;
+use bound_stream::BoundJabberStream;
+use jid::{FullJID, JID};
use peanuts::IntoElement;
#[cfg(target_arch = "wasm32")]
use peanuts::WebSocketOnMessageRead;
@@ -147,9 +148,9 @@ impl JabberStream {
}
#[instrument]
- pub async fn bind(mut self, jid: &mut JID) -> Result<Self> {
+ pub async fn bind(mut self, jid: &JID) -> Result<(BoundJabberStream, FullJID)> {
let iq_id = uuid::Uuid::new_v4().to_string();
- if let Some(resource) = &jid.resourcepart {
+ if let Some(resource) = &jid.resourcepart() {
let iq = Iq {
from: None,
id: iq_id.clone(),
@@ -176,8 +177,7 @@ impl JabberStream {
})),
errors: _,
} if id == iq_id => {
- *jid = new_jid;
- return Ok(self);
+ return Ok((self.to_bound_jabber(), new_jid));
}
Iq {
from: _,
@@ -219,8 +219,7 @@ impl JabberStream {
})),
errors: _,
} if id == iq_id => {
- *jid = new_jid;
- return Ok(self);
+ return Ok((self.to_bound_jabber(), new_jid));
}
Iq {
from: _,
@@ -257,7 +256,11 @@ impl JabberStream {
id: None,
lang: None,
version: Some("1.0".to_string()),
- to: Some(JID::from_str(server.as_ref())?),
+ to: Some(
+ JID::from_str(server.as_ref())
+ .map_err(|e| Error::JID(e.into()))?
+ .try_into()?,
+ ),
};
writer.write(&open).await?;
@@ -290,7 +293,9 @@ impl JabberStream {
// opening stream element
let stream = Stream::new_client(
None,
- JID::from_str(server.as_ref())?,
+ JID::from_str(server.as_ref())
+ .map_err(|e| Error::JID(e.into()))?
+ .try_into()?,
None,
"en".to_string(),
);
diff --git a/stanza/src/bind.rs b/stanza/src/bind.rs
index 3ce2246..0f0f681 100644
--- a/stanza/src/bind.rs
+++ b/stanza/src/bind.rs
@@ -1,4 +1,4 @@
-use jid::JID;
+use jid::FullJID;
use peanuts::{Element, FromElement, IntoElement};
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-bind";
@@ -54,7 +54,7 @@ impl IntoElement for BindType {
// minLength 8 maxLength 3071
#[derive(Clone, Debug)]
-pub struct FullJidType(pub JID);
+pub struct FullJidType(pub FullJID);
impl FromElement for FullJidType {
fn from_element(mut element: peanuts::Element) -> peanuts::DeserializeResult<Self> {
diff --git a/stanza/src/rfc_7395.rs b/stanza/src/rfc_7395.rs
index 64d9f70..73e947d 100644
--- a/stanza/src/rfc_7395.rs
+++ b/stanza/src/rfc_7395.rs
@@ -1,12 +1,12 @@
-use jid::JID;
+use jid::BareJID;
use peanuts::{Element, ElementBuilder, FromElement, IntoElement};
pub const XMLNS: &str = "urn:ietf:params:xml:ns:xmpp-framing";
#[derive(Debug)]
pub struct Open {
- pub from: Option<JID>,
- pub to: Option<JID>,
+ pub from: Option<BareJID>,
+ pub to: Option<BareJID>,
pub id: Option<String>,
pub version: Option<String>,
pub lang: Option<String>,
@@ -46,8 +46,8 @@ impl IntoElement for Open {
#[derive(Debug, Default)]
pub struct Close {
- pub from: Option<JID>,
- pub to: Option<JID>,
+ pub from: Option<BareJID>,
+ pub to: Option<BareJID>,
pub id: Option<String>,
pub version: Option<String>,
pub lang: Option<String>,
diff --git a/stanza/src/roster.rs b/stanza/src/roster.rs
index 14f65ef..dcbf017 100644
--- a/stanza/src/roster.rs
+++ b/stanza/src/roster.rs
@@ -1,6 +1,6 @@
use std::str::FromStr;
-use jid::JID;
+use jid::BareJID;
use peanuts::{DeserializeError, Element, FromElement, IntoElement};
pub const XMLNS: &str = "jabber:iq:roster";
@@ -38,7 +38,7 @@ pub struct Item {
/// signals subscription sub-states (server only)
pub ask: bool,
/// uniquely identifies item
- pub jid: JID,
+ pub jid: BareJID,
/// handle that is determined by user, not contact
pub name: Option<String>,
/// state of the presence subscription
diff --git a/stanza/src/stream.rs b/stanza/src/stream.rs
index 5be235a..e2f4f9b 100644
--- a/stanza/src/stream.rs
+++ b/stanza/src/stream.rs
@@ -1,6 +1,6 @@
use std::fmt::Display;
-use jid::JID;
+use jid::BareJID;
use peanuts::{Element, ElementBuilder, FromElement, IntoElement};
use thiserror::Error;
@@ -18,8 +18,8 @@ pub const XMLNS: &str = "http://etherx.jabber.org/streams";
// #[peanuts(xmlns = XMLNS)]
#[derive(Debug)]
pub struct Stream {
- pub from: Option<JID>,
- to: Option<JID>,
+ pub from: Option<BareJID>,
+ to: Option<BareJID>,
id: Option<String>,
version: Option<String>,
// TODO: lang enum
@@ -64,8 +64,8 @@ impl IntoElement for Stream {
impl<'s> Stream {
pub fn new(
- from: Option<JID>,
- to: Option<JID>,
+ from: Option<BareJID>,
+ to: Option<BareJID>,
id: Option<String>,
version: Option<String>,
lang: Option<String>,
@@ -81,7 +81,12 @@ impl<'s> Stream {
/// For initial stream headers, the initiating entity SHOULD include the 'xml:lang' attribute.
/// For privacy, it is better to not set `from` when sending a client stanza over an unencrypted connection.
- pub fn new_client(from: Option<JID>, to: JID, id: Option<String>, lang: String) -> Self {
+ pub fn new_client(
+ from: Option<BareJID>,
+ to: BareJID,
+ id: Option<String>,
+ lang: String,
+ ) -> Self {
Self {
from,
to: Some(to),
diff --git a/stanza/src/xep_0060/owner.rs b/stanza/src/xep_0060/owner.rs
index 0617712..4876bf5 100644
--- a/stanza/src/xep_0060/owner.rs
+++ b/stanza/src/xep_0060/owner.rs
@@ -1,6 +1,6 @@
use std::str::FromStr;
-use jid::JID;
+use jid::{BareJID, JID};
use peanuts::{DeserializeError, Element, FromElement, IntoElement};
use crate::xep_0004::X;
@@ -85,7 +85,7 @@ impl IntoElement for Affiliations {
#[derive(Clone, Debug)]
pub struct Affiliation {
affiliation: AffiliationType,
- jid: JID,
+ jid: BareJID,
}
impl FromElement for Affiliation {