Remove the -rs suffix of jid, minidom and xmpp

We know those are Rust libraries, no need to add it to the path.  This
synchronises their directory with the crate name, hopefully reducing
confusion.
This commit is contained in:
Emmanuel Gil Peyrot 2020-06-22 02:17:32 +02:00
commit 714d850e69
28 changed files with 6 additions and 6 deletions

93
xmpp/src/pubsub/avatar.rs Normal file
View file

@ -0,0 +1,93 @@
// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use super::Agent;
use crate::Event;
use std::convert::TryFrom;
use std::fs::{self, File};
use std::io::{self, Write};
use xmpp_parsers::{
avatar::{Data, Metadata},
iq::Iq,
ns,
pubsub::{
event::Item,
pubsub::{Items, PubSub},
NodeName,
},
Jid,
};
pub(crate) async fn handle_metadata_pubsub_event(
from: &Jid,
agent: &mut Agent,
items: Vec<Item>,
) -> Vec<Event> {
let mut events = Vec::new();
for item in items {
let payload = item.payload.clone().unwrap();
if payload.is("metadata", ns::AVATAR_METADATA) {
let metadata = Metadata::try_from(payload).unwrap();
for info in metadata.infos {
let filename = format!("data/{}/{}", from, &*info.id.to_hex());
let file_length = match fs::metadata(filename.clone()) {
Ok(metadata) => metadata.len(),
Err(_) => 0,
};
// TODO: Also check the hash.
if info.bytes as u64 == file_length {
events.push(Event::AvatarRetrieved(from.clone(), filename));
} else {
let iq = download_avatar(from);
let _ = agent.client.send_stanza(iq.into()).await;
}
}
}
}
events
}
fn download_avatar(from: &Jid) -> Iq {
Iq::from_get(
"coucou",
PubSub::Items(Items {
max_items: None,
node: NodeName(String::from(ns::AVATAR_DATA)),
subid: None,
items: Vec::new(),
}),
)
.with_to(from.clone())
}
// The return value of this function will be simply pushed to a Vec in the caller function,
// so it makes no sense to allocate a Vec here - we're lazy instead
pub(crate) fn handle_data_pubsub_iq<'a>(
from: &'a Jid,
items: &'a Items,
) -> impl IntoIterator<Item = Event> + 'a {
let from = from.clone();
items
.items
.iter()
.filter_map(move |item| match (&item.id, &item.payload) {
(Some(id), Some(payload)) => {
let data = Data::try_from(payload.clone()).unwrap();
let filename = save_avatar(&from, id.0.clone(), &data.data).unwrap();
Some(Event::AvatarRetrieved(from.clone(), filename))
}
_ => None,
})
}
fn save_avatar(from: &Jid, id: String, data: &[u8]) -> io::Result<String> {
let directory = format!("data/{}", from);
let filename = format!("data/{}/{}", from, id);
fs::create_dir_all(directory)?;
let mut file = File::create(&filename)?;
file.write_all(data)?;
Ok(filename)
}

112
xmpp/src/pubsub/mod.rs Normal file
View file

@ -0,0 +1,112 @@
// Copyright (c) 2019 Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
use super::Agent;
use crate::Event;
use std::convert::TryFrom;
use std::str::FromStr;
use xmpp_parsers::{
bookmarks2::{Autojoin, Conference},
ns,
pubsub::event::PubSubEvent,
pubsub::pubsub::PubSub,
BareJid, Element, Jid,
};
#[cfg(feature = "avatars")]
pub(crate) mod avatar;
pub(crate) async fn handle_event(from: &Jid, elem: Element, agent: &mut Agent) -> Vec<Event> {
let mut events = Vec::new();
let event = PubSubEvent::try_from(elem);
trace!("PubSub event: {:#?}", event);
match event {
Ok(PubSubEvent::PublishedItems { node, items }) => {
match node.0 {
#[cfg(feature = "avatars")]
ref node if node == ns::AVATAR_METADATA => {
let new_events =
avatar::handle_metadata_pubsub_event(&from, agent, items).await;
events.extend(new_events);
}
ref node if node == ns::BOOKMARKS2 => {
// TODO: Check that our bare JID is the sender.
assert_eq!(items.len(), 1);
let item = items.clone().pop().unwrap();
let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
let payload = item.payload.clone().unwrap();
match Conference::try_from(payload) {
Ok(conference) => {
if conference.autojoin == Autojoin::True {
events.push(Event::JoinRoom(jid, conference));
} else {
events.push(Event::LeaveRoom(jid));
}
}
Err(err) => println!("not bookmark: {}", err),
}
}
ref node => unimplemented!("node {}", node),
}
}
Ok(PubSubEvent::RetractedItems { node, items }) => {
match node.0 {
ref node if node == ns::BOOKMARKS2 => {
// TODO: Check that our bare JID is the sender.
assert_eq!(items.len(), 1);
let item = items.clone().pop().unwrap();
let jid = BareJid::from_str(&item.0).unwrap();
events.push(Event::LeaveRoom(jid));
}
ref node => unimplemented!("node {}", node),
}
}
Ok(PubSubEvent::Purge { node }) => {
match node.0 {
ref node if node == ns::BOOKMARKS2 => {
// TODO: Check that our bare JID is the sender.
events.push(Event::LeaveAllRooms);
}
ref node => unimplemented!("node {}", node),
}
}
_ => unimplemented!(),
}
events
}
pub(crate) fn handle_iq_result(from: &Jid, elem: Element) -> impl IntoIterator<Item = Event> {
let mut events = Vec::new();
let pubsub = PubSub::try_from(elem).unwrap();
trace!("PubSub: {:#?}", pubsub);
if let PubSub::Items(items) = pubsub {
match items.node.0.clone() {
#[cfg(feature = "avatars")]
ref node if node == ns::AVATAR_DATA => {
let new_events = avatar::handle_data_pubsub_iq(&from, &items);
events.extend(new_events);
}
ref node if node == ns::BOOKMARKS2 => {
events.push(Event::LeaveAllRooms);
for item in items.items {
let item = item.0;
let jid = BareJid::from_str(&item.id.clone().unwrap().0).unwrap();
let payload = item.payload.clone().unwrap();
match Conference::try_from(payload) {
Ok(conference) => {
if let Autojoin::True = conference.autojoin {
events.push(Event::JoinRoom(jid, conference));
}
}
Err(err) => panic!("Wrong payload type in bookmarks 2 item: {}", err),
}
}
}
_ => unimplemented!(),
}
}
events
}