2022-12-17 00:17:53 +01:00
|
|
|
use std::str::FromStr;
|
|
|
|
use std::convert::TryFrom;
|
|
|
|
use futures::{SinkExt, StreamExt};
|
|
|
|
use tokio::sync::mpsc;
|
|
|
|
use tokio_xmpp::{AsyncClient, Packet, Event};
|
|
|
|
use xmpp_parsers::{Jid, BareJid, FullJid, Element};
|
|
|
|
use xmpp_parsers::message::{Body, Message, MessageType};
|
|
|
|
use xmpp_parsers::presence::{Presence, Show as PresenceShow, Type as PresenceType};
|
|
|
|
use xmpp_parsers::muc::Muc;
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub struct Handle {
|
|
|
|
room_jid: BareJid,
|
|
|
|
tx: mpsc::Sender<Packet>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Handle {
|
|
|
|
pub async fn send_message(&self, msg: String) {
|
|
|
|
let stanza = make_room_message(self.room_jid.clone(), msg);
|
|
|
|
self.tx.send(Packet::Stanza(stanza)).await.unwrap();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn run(jid: String, password: String, muc_jid: String) -> Handle {
|
|
|
|
let muc_jid: FullJid = match FullJid::from_str(&muc_jid) {
|
|
|
|
Ok(jid) => jid,
|
|
|
|
Err(err) => panic!("MUC Jid invalid: {:?}", err),
|
|
|
|
};
|
|
|
|
let (tx, mut rx) = mpsc::channel(1);
|
|
|
|
let handle = Handle {
|
|
|
|
room_jid: muc_jid.clone().into(),
|
|
|
|
tx: tx.clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
let mut client = AsyncClient::new(&jid, &password).unwrap();
|
|
|
|
loop {
|
|
|
|
match client.next().await {
|
|
|
|
Some(Event::Online { .. }) => {
|
|
|
|
println!("XMPP client now online at {}", jid);
|
|
|
|
let packet = Packet::Stanza(make_join_presence(muc_jid.clone()));
|
|
|
|
client.send(packet).await
|
|
|
|
.unwrap();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Some(_) => {}
|
|
|
|
None => panic!("XMPP cannot connect"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let (mut sink, mut stream) = client.split();
|
|
|
|
tokio::spawn(async move {
|
|
|
|
while let Some(event) = stream.next().await {
|
|
|
|
match event {
|
|
|
|
Event::Stanza(el) => {
|
|
|
|
if el.is("presence", "jabber:client") {
|
|
|
|
match Presence::try_from(el) {
|
|
|
|
Ok(presence) => {
|
|
|
|
if presence.from == Some(Jid::Full(muc_jid.clone())) {
|
|
|
|
if presence.type_ == PresenceType::Error {
|
|
|
|
println!("Failed to enter MUC {:?}", muc_jid);
|
|
|
|
} else {
|
|
|
|
println!("Entered MUC {:?}", muc_jid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
Err(err) => println!("Received invalid presence: {:?}", err),
|
|
|
|
}
|
|
|
|
}
|
2022-12-17 00:20:30 +01:00
|
|
|
systemd::daemon::notify(false, [(systemd::daemon::STATE_WATCHDOG, "1")].iter())
|
|
|
|
.unwrap();
|
2022-12-17 00:17:53 +01:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
panic!("XMPP end")
|
|
|
|
});
|
|
|
|
tokio::spawn(async move {
|
|
|
|
while let Some(packet) = rx.recv().await {
|
|
|
|
sink.send(packet).await.unwrap();
|
|
|
|
}
|
|
|
|
|
|
|
|
panic!("channel end")
|
|
|
|
});
|
|
|
|
|
|
|
|
handle
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn make_room_message(room_jid: BareJid, text: String) -> Element {
|
|
|
|
let mut message = Message::new(Some(Jid::Bare(room_jid)));
|
|
|
|
message.type_ = MessageType::Groupchat;
|
|
|
|
message.bodies.insert("de".to_string(), Body(text));
|
|
|
|
message.into()
|
|
|
|
}
|
|
|
|
|
|
|
|
fn make_join_presence(muc_jid: FullJid) -> Element {
|
|
|
|
let mut presence = Presence::new(PresenceType::None)
|
|
|
|
.with_to(Jid::Full(muc_jid))
|
|
|
|
.with_show(PresenceShow::Dnd);
|
|
|
|
presence.set_status("de".to_string(), "Augen und Ohren nach oben".to_string());
|
|
|
|
presence.add_payload(Muc::new());
|
|
|
|
presence.into()
|
|
|
|
}
|