7WM64CI7MA25GOY5BEQQQFUXNKLXSAN65VX7XA3UGJKGS6OVLUAQC
NXDEBFWRTMIXUI4G4QV67Z3C2AH7YL777F3V42XMEP3Q6LC63SOAC
KORYGY74MKXQZSV6JOJJCHPG3CC5UM2LTNIEV5UAJGZS7QCDKDLQC
CCLGGFKRUNXBM6IOGEYJOFULCSVOL6C5PFAGCKEWNXOZIKPWLLWQC
LL3D5CXKPWIGTQ7MFK4YXDGDZOKD6CU5WCIWV3FG6TPGQOGD75QAC
FVVPKFTLD5VOGVDF7MOSSKQ3KPCT4HDGTNTTC6I6B4TWXOTPCJ7AC
JY4F7VBCS4S2YYXT7JQBLPSCWW3K4H3NXH6G5WGJFWWQXN2YPIQAC
fn process_jid(&mut self, xmpp_to: &xmpp_parsers::Jid) {
if let Some(ref mut mailbox) = self.state.data.outgoing_mailbox.get_mut(xmpp_to) {
if !mailbox.is_empty() {
if let Some(ref mut rdata) = self
.state
.data
.roster
.get_mut(&std::convert::From::from(xmpp_to.clone()))
{
info!("Jid {} in roster", xmpp_to);
let sub_to = match rdata.0 {
xmpp_parsers::roster::Subscription::To => true,
xmpp_parsers::roster::Subscription::Both => true,
_ => false,
};
if sub_to {
info!("Subscribed to {}", xmpp_to);
self.state.data.send_queue.extend(
mailbox.drain(..).map(|message| {
stanzas::make_chat_message(xmpp_to.clone(), message)
}),
);
} else if rdata.1 == xmpp_parsers::roster::Ask::None {
info!("Not subscribed to {}", xmpp_to);
self.state.data.counter += 1;
let id_presence_subscribe =
format!("id_presence_subscribe{}", self.state.data.counter);
self.state
.data
.send_queue
.push_back(stanzas::make_ask_subscribe(
id_presence_subscribe,
xmpp_to.clone(),
));
} else {
warn!(
"Not subscribed to {}. Currently in {:?} state",
xmpp_to, rdata.1
);
self.state.data.counter += 1;
let id_presence_subscribe =
format!("id_presence_subscribe{}", self.state.data.counter);
self.state
.data
.send_queue
.push_back(stanzas::make_ask_subscribe(
id_presence_subscribe,
xmpp_to.clone(),
));
}
let sub_from = match rdata.0 {
xmpp_parsers::roster::Subscription::From => true,
xmpp_parsers::roster::Subscription::Both => true,
_ => false,
};
if !sub_from {
info!("Not subscription from {}", xmpp_to);
self.state.data.counter += 1;
let id_presence_subscribed =
format!("id_presence_subscribed{}", self.state.data.counter);
self.state
.data
.send_queue
.push_back(stanzas::make_allow_subscribe(
id_presence_subscribed,
xmpp_to.clone(),
));
}
} else {
info!("Jid {} not in roster", xmpp_to);
self.state.data.counter += 1;
let id_add_roster = format!("id_add_roster{}", self.state.data.counter);
let add_roster = stanzas::make_add_roster(
&id_add_roster,
std::convert::From::from(xmpp_to.clone()),
);
info!("Adding jid {} to roster id {}", xmpp_to, id_add_roster);
self.state.data.pending_ids.insert(
id_add_roster,
IqWait::new(
60,
AddRosterIqHandler {
jid: std::convert::From::from(xmpp_to.clone()),
},
),
);
self.state.data.send_queue.push_back(add_roster);
}
}
}
}
XmppCommand::Chat { xmpp_to, message } => {
self.state
.data
.outgoing_mailbox
.entry(xmpp_to.clone())
.or_default()
.push(message);
self.process_jid(&xmpp_to);
}
XmppCommand::Chatroom { muc_id, message } => {
if let Some(muc) = self.state.data.mucs.get(&muc_id) {
self.state
.data
.send_queue
.push_back(stanzas::make_muc_message(muc.clone(), message));
} else {
error!("Not found MUC {}", muc_id);
}
}
XmppCommand::ChatroomPresence {
muc_id,
show,
message,
} => {
if let Some(muc) = self.state.data.mucs.get(&muc_id) {
self.state.data.counter += 1;
let id_presence = format!("id_presence{}", self.state.data.counter);
self.state
.data
.send_queue
.push_back(stanzas::make_muc_presence(
&id_presence,
self.account.jid.clone(),
muc.clone(),
Some(show),
Some(message),
));
} else {
error!("Not found MUC {}", muc_id);
}
}
type Func<S, T, E> = dyn Fn(&mut S, E) -> T + Sync;
pub struct Processor<S: 'static, T: 'static, E: Clone + 'static> {
processors: Vec<Box<Func<S, Option<T>, E>>>,
default: &'static Func<S, T, E>,
}
impl<S: 'static, T: 'static, E: Clone + 'static> Processor<S, T, E> {
pub fn new<F>(f: &'static F) -> Processor<S, T, E>
where
F: Fn(&mut S, E) -> T + Sync + 'static,
{
Processor {
processors: vec![],
default: f,
}
}
pub fn register<F, A>(&mut self, f: &'static F)
where
F: Fn(&mut S, A) -> T + Sync + 'static,
A: std::convert::TryFrom<E>,
{
self.processors.push(Box::new(move |s, e: E| {
use std::convert::TryInto;
(e.try_into().ok() as Option<A>).map(|a| f(s, a))
}));
}
pub fn process(&self, s: &mut S, e: E) -> T {
for processor in self.processors.iter() {
match processor(s, e.clone()) {
Some(t) => return t,
None => continue,
}
}
(*self.default)(s, e)
}
}
type Func<S, T, E> = dyn Fn(&mut S, E) -> T + Sync;
pub struct Processor<S: 'static, T: 'static, E: Clone + 'static> {
processors: Vec<Box<Func<S, Option<T>, E>>>,
default: &'static Func<S, T, E>,
}
impl<S: 'static, T: 'static, E: Clone + 'static> Processor<S, T, E> {
pub fn new<F>(f: &'static F) -> Processor<S, T, E>
where
F: Fn(&mut S, E) -> T + Sync + 'static,
{
Processor {
processors: vec![],
default: f,
}
}
pub fn register<F, A>(&mut self, f: &'static F)
where
F: Fn(&mut S, A) -> T + Sync + 'static,
A: std::convert::TryFrom<E>,
{
self.processors.push(Box::new(move |s, e: E| {
use std::convert::TryInto;
(e.try_into().ok() as Option<A>).map(|a| f(s, a))
}));
}
pub fn process(&self, s: &mut S, e: E) -> T {
for processor in self.processors.iter() {
match processor(s, e.clone()) {
Some(t) => return t,
None => continue,
}
}
(*self.default)(s, e)
}
}
.body(Body::from(format!("Cann't get presence text")))
.body(Body::from(format!("Cann't send command")))
.map_err(std::convert::Into::into)
}
}
}
Err(e) => Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("Cann't get presence text")))
.map_err(std::convert::Into::into),
}
})
}
(None, Ok(xmpp_to), _) => {
info!("Got chat request. Reading body...");
let mut cmd_send = self.cmd_send.clone();
Box::pin(async move {
match body_to_string(req).await {
Ok(message) => {
match cmd_send.send(XmppCommand::Chat { xmpp_to, message }).await {
Ok(_) => Response::builder()
.body(Body::from(format!("Accepted")))
.map_err(std::convert::Into::into),
Err(e) => {
error!("Cann't send chat command: {}", e);
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("Cann't send command")))
.map_err(std::convert::Into::into)
}
}
}
Err(e) => Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("Cann't get chat text")))
.map_err(std::convert::Into::into),
}
})
}
(Some(Ok(muc_id)), _, Ok(show)) => {
info!("Got MUC presence request. Reading body...");
let mut cmd_send = self.cmd_send.clone();
Box::pin(async move {
match body_to_string(req).await {
Ok(message) => {
match cmd_send
.send(XmppCommand::ChatroomPresence {
muc_id,
show,
message,
})
.await
{
Ok(_) => Response::builder()
.body(Body::from(format!("Accepted")))
.map_err(std::convert::Into::into),
Err(e) => {
error!("Cann't send MUC presence command: {}", e);
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("Cann't send command")))
(None, Ok(xmpp_to), _) => Box::pin(async {
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("SOON")))
.map_err(std::convert::Into::into)
}),
(Some(Ok(muc_id)), _, Ok(show)) => Box::pin(async {
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("SOON")))
.map_err(std::convert::Into::into)
}),
(Some(Ok(muc_id)), _, _) => Box::pin(async {
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("SOON")))
.map_err(std::convert::Into::into)
}),
(Some(Err(err)), _, _) => Box::pin(async {
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("SOON")))
.map_err(std::convert::Into::into)
}),
(Some(Ok(muc_id)), _, _) => {
info!("Got MUC chat request. Reading body...");
let mut cmd_send = self.cmd_send.clone();
Box::pin(async move {
match body_to_string(req).await {
Ok(message) => {
match cmd_send
.send(XmppCommand::Chatroom { muc_id, message })
.await
{
Ok(_) => Response::builder()
.body(Body::from(format!("Accepted")))
.map_err(std::convert::Into::into),
Err(e) => {
error!("Cann't send MUC chat command: {}", e);
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("Cann't send command")))
.map_err(std::convert::Into::into)
}
}
}
Err(e) => Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("Cann't get chat text")))
.map_err(std::convert::Into::into),
}
})
}
(Some(Err(err)), _, _) => {
warn!("Unknown muc destination: {}", err);
Box::pin(async move {
Response::builder()
.status(hyper::StatusCode::BAD_REQUEST)
.body(Body::from(format!("Unknown muc destination: {}", err,)))
.map_err(std::convert::Into::into)
})
}