mirror of
https://gitlab.com/xmpp-rs/xmpp-rs.git
synced 2024-07-12 22:21:53 +00:00
Merge branch 'disco' into 'master'
Add a disco plugin See merge request !11
This commit is contained in:
commit
f10080cba5
5 changed files with 170 additions and 0 deletions
|
@ -6,6 +6,7 @@ use xmpp::plugins::stanza::StanzaPlugin;
|
|||
use xmpp::plugins::unhandled_iq::UnhandledIqPlugin;
|
||||
use xmpp::plugins::messaging::{MessagingPlugin, MessageEvent};
|
||||
use xmpp::plugins::presence::{PresencePlugin, Type};
|
||||
use xmpp::plugins::disco::DiscoPlugin;
|
||||
use xmpp::plugins::ibb::IbbPlugin;
|
||||
use xmpp::plugins::ping::PingPlugin;
|
||||
use xmpp::event::{Priority, Propagation};
|
||||
|
@ -23,8 +24,11 @@ fn main() {
|
|||
client.register_plugin(UnhandledIqPlugin::new());
|
||||
client.register_plugin(MessagingPlugin::new());
|
||||
client.register_plugin(PresencePlugin::new());
|
||||
client.register_plugin(DiscoPlugin::new("client", "bot", "en", "xmpp-rs"));
|
||||
client.register_plugin(IbbPlugin::new());
|
||||
client.register_plugin(PingPlugin::new());
|
||||
client.plugin::<PingPlugin>().init();
|
||||
client.plugin::<IbbPlugin>().init();
|
||||
client.register_handler(Priority::Max, |e: &MessageEvent| {
|
||||
println!("{:?}", e);
|
||||
Propagation::Continue
|
||||
|
|
125
src/plugins/disco.rs
Normal file
125
src/plugins/disco.rs
Normal file
|
@ -0,0 +1,125 @@
|
|||
use std::convert::TryFrom;
|
||||
use std::sync::{Mutex, Arc};
|
||||
|
||||
use plugin::PluginProxy;
|
||||
use event::{Event, Priority, Propagation};
|
||||
use jid::Jid;
|
||||
|
||||
use plugins::stanza::Iq;
|
||||
use xmpp_parsers::iq::{IqType, IqPayload};
|
||||
use xmpp_parsers::disco::{Disco, Identity, Feature};
|
||||
use xmpp_parsers::data_forms::DataForm;
|
||||
use xmpp_parsers::ns;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DiscoInfoRequest {
|
||||
pub from: Jid,
|
||||
pub id: String,
|
||||
pub node: Option<String>,
|
||||
}
|
||||
|
||||
impl Event for DiscoInfoRequest {}
|
||||
|
||||
pub struct DiscoPlugin {
|
||||
proxy: PluginProxy,
|
||||
cached_disco: Arc<Mutex<Disco>>,
|
||||
}
|
||||
|
||||
impl DiscoPlugin {
|
||||
pub fn new(category: &str, type_: &str, lang: &str, name: &str) -> DiscoPlugin {
|
||||
DiscoPlugin {
|
||||
proxy: PluginProxy::new(),
|
||||
cached_disco: Arc::new(Mutex::new(Disco {
|
||||
node: None,
|
||||
identities: vec!(Identity {
|
||||
category: category.to_owned(),
|
||||
type_: type_.to_owned(),
|
||||
lang: Some(lang.to_owned()),
|
||||
name: Some(name.to_owned())
|
||||
}),
|
||||
features: vec!(Feature { var: String::from(ns::DISCO_INFO) }),
|
||||
extensions: vec!(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_identity(&self, category: &str, type_: &str, lang: Option<&str>, name: Option<&str>) {
|
||||
let mut cached_disco = self.cached_disco.lock().unwrap();
|
||||
cached_disco.identities.push(Identity {
|
||||
category: category.to_owned(),
|
||||
type_: type_.to_owned(),
|
||||
lang: lang.and_then(|lang| Some(lang.to_owned())),
|
||||
name: name.and_then(|name| Some(name.to_owned())),
|
||||
});
|
||||
}
|
||||
|
||||
pub fn remove_identity(&self, category: &str, type_: &str, lang: Option<&str>, name: Option<&str>) {
|
||||
let mut cached_disco = self.cached_disco.lock().unwrap();
|
||||
cached_disco.identities.retain(|identity| {
|
||||
identity.category != category ||
|
||||
identity.type_ != type_ ||
|
||||
identity.lang != lang.and_then(|lang| Some(lang.to_owned())) ||
|
||||
identity.name != name.and_then(|name| Some(name.to_owned()))
|
||||
});
|
||||
}
|
||||
|
||||
pub fn add_feature(&self, var: &str) {
|
||||
let mut cached_disco = self.cached_disco.lock().unwrap();
|
||||
cached_disco.features.push(Feature { var: String::from(var) });
|
||||
}
|
||||
|
||||
pub fn remove_feature(&self, var: &str) {
|
||||
let mut cached_disco = self.cached_disco.lock().unwrap();
|
||||
cached_disco.features.retain(|feature| feature.var != var);
|
||||
}
|
||||
|
||||
pub fn add_extension(&self, extension: DataForm) {
|
||||
let mut cached_disco = self.cached_disco.lock().unwrap();
|
||||
cached_disco.extensions.push(extension);
|
||||
}
|
||||
|
||||
pub fn remove_extension(&self, form_type: &str) {
|
||||
let mut cached_disco = self.cached_disco.lock().unwrap();
|
||||
cached_disco.extensions.retain(|extension| {
|
||||
extension.form_type != Some(form_type.to_owned())
|
||||
});
|
||||
}
|
||||
|
||||
fn handle_iq(&self, iq: &Iq) -> Propagation {
|
||||
let iq = iq.clone();
|
||||
if let IqType::Get(payload) = iq.payload {
|
||||
// TODO: use an intermediate plugin to parse this payload.
|
||||
if let Ok(IqPayload::Disco(disco)) = IqPayload::try_from(payload) {
|
||||
self.proxy.dispatch(DiscoInfoRequest { // TODO: safety!!!
|
||||
from: iq.from.unwrap(),
|
||||
id: iq.id.unwrap(),
|
||||
node: disco.node,
|
||||
});
|
||||
return Propagation::Stop;
|
||||
}
|
||||
}
|
||||
Propagation::Continue
|
||||
}
|
||||
|
||||
fn reply_disco_info(&self, request: &DiscoInfoRequest) -> Propagation {
|
||||
let payload = if request.node.is_none() {
|
||||
let cached_disco = self.cached_disco.lock().unwrap().clone();
|
||||
IqType::Result(Some(cached_disco.into()))
|
||||
} else {
|
||||
// TODO: handle the requests on nodes too.
|
||||
return Propagation::Continue;
|
||||
};
|
||||
self.proxy.send(Iq {
|
||||
from: None,
|
||||
to: Some(request.from.to_owned()),
|
||||
id: Some(request.id.to_owned()),
|
||||
payload,
|
||||
}.into());
|
||||
Propagation::Stop
|
||||
}
|
||||
}
|
||||
|
||||
impl_plugin!(DiscoPlugin, proxy, [
|
||||
(Iq, Priority::Default) => handle_iq,
|
||||
(DiscoInfoRequest, Priority::Default) => reply_disco_info,
|
||||
]);
|
|
@ -8,9 +8,11 @@ use event::{Event, Priority, Propagation};
|
|||
use jid::Jid;
|
||||
|
||||
use plugins::stanza::Iq;
|
||||
use plugins::disco::DiscoPlugin;
|
||||
use xmpp_parsers::iq::{IqType, IqPayload};
|
||||
use xmpp_parsers::ibb::{IBB, Stanza};
|
||||
use xmpp_parsers::stanza_error::{StanzaError, ErrorType, DefinedCondition};
|
||||
use xmpp_parsers::ns;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Session {
|
||||
|
@ -66,6 +68,24 @@ impl IbbPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: make that called automatically after plugins are created.
|
||||
pub fn init(&self) {
|
||||
if let Some(disco) = self.proxy.plugin::<DiscoPlugin>() {
|
||||
disco.add_feature(ns::IBB);
|
||||
} else {
|
||||
panic!("Please handle dependencies in the correct order.");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make that called automatically before removal.
|
||||
pub fn deinit(&self) {
|
||||
if let Some(disco) = self.proxy.plugin::<DiscoPlugin>() {
|
||||
disco.remove_feature(ns::IBB);
|
||||
} else {
|
||||
panic!("Please handle dependencies in the correct order.");
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_ibb(&self, from: Jid, ibb: IBB) -> Result<(), StanzaError> {
|
||||
let mut sessions = self.sessions.lock().unwrap();
|
||||
match ibb {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
pub mod messaging;
|
||||
pub mod presence;
|
||||
pub mod disco;
|
||||
pub mod ping;
|
||||
pub mod ibb;
|
||||
pub mod stanza;
|
||||
|
|
|
@ -6,8 +6,10 @@ use error::Error;
|
|||
use jid::Jid;
|
||||
|
||||
use plugins::stanza::Iq;
|
||||
use plugins::disco::DiscoPlugin;
|
||||
use xmpp_parsers::iq::{IqType, IqPayload};
|
||||
use xmpp_parsers::ping::Ping;
|
||||
use xmpp_parsers::ns;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PingEvent {
|
||||
|
@ -28,6 +30,24 @@ impl PingPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: make that called automatically after plugins are created.
|
||||
pub fn init(&self) {
|
||||
if let Some(disco) = self.proxy.plugin::<DiscoPlugin>() {
|
||||
disco.add_feature(ns::PING);
|
||||
} else {
|
||||
panic!("Please handle dependencies in the correct order.");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: make that called automatically before removal.
|
||||
pub fn deinit(&self) {
|
||||
if let Some(disco) = self.proxy.plugin::<DiscoPlugin>() {
|
||||
disco.remove_feature(ns::PING);
|
||||
} else {
|
||||
panic!("Please handle dependencies in the correct order.");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_ping(&self, to: &Jid) -> Result<(), Error> {
|
||||
let to = to.clone();
|
||||
self.proxy.send(Iq {
|
||||
|
|
Loading…
Reference in a new issue