126 lines
3.1 KiB
Rust
126 lines
3.1 KiB
Rust
// Copyright (C) 2023-2099 The crate authors.
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify it
|
|
// under the terms of the GNU Affero General Public License as published by the
|
|
// Free Software Foundation, either version 3 of the License, or (at your
|
|
// option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License
|
|
// for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
use crate::hooks::{format_hook, Hook};
|
|
use crate::Error;
|
|
|
|
use log::debug;
|
|
use tokio::{signal::ctrl_c, sync::mpsc};
|
|
use xmpp::jid::{BareJid, Jid, ResourcePart};
|
|
use xmpp::parsers::message::MessageType;
|
|
use xmpp::{
|
|
message::send::RawMessageSettings, muc::room::JoinRoomSettings, Agent, ClientBuilder,
|
|
ClientFeature, ClientType, Event, RoomNick,
|
|
};
|
|
|
|
pub struct XmppClient {
|
|
is_online: bool,
|
|
agent: Agent,
|
|
rooms: Vec<BareJid>,
|
|
nickname: ResourcePart,
|
|
}
|
|
|
|
impl XmppClient {
|
|
pub fn new(
|
|
jid: BareJid,
|
|
password: &str,
|
|
rooms: Vec<BareJid>,
|
|
nickname: ResourcePart,
|
|
) -> XmppClient {
|
|
let agent = ClientBuilder::new(jid, password)
|
|
.set_client(ClientType::Bot, "xmpp-rs")
|
|
.set_website("https://gitlab.com/xmpp-rs/xmpp-rs")
|
|
.set_default_nick(&nickname)
|
|
.enable_feature(ClientFeature::JoinRooms)
|
|
.build();
|
|
|
|
XmppClient {
|
|
is_online: false,
|
|
agent,
|
|
rooms,
|
|
nickname,
|
|
}
|
|
}
|
|
|
|
pub async fn next(&mut self) {
|
|
for event in self.agent.wait_for_events().await {
|
|
match event {
|
|
Event::Online => {
|
|
self.is_online = true;
|
|
debug!("XMPP Online");
|
|
|
|
for room in &self.rooms {
|
|
self.agent
|
|
.join_room(JoinRoomSettings {
|
|
room: room.clone(),
|
|
nick: Some(RoomNick::from_resource_ref(self.nickname.as_ref())),
|
|
password: None,
|
|
status: Some(("en", "Hi there!")),
|
|
})
|
|
.await
|
|
}
|
|
}
|
|
Event::Disconnected(e) => {
|
|
self.is_online = false;
|
|
debug!("XMPP Disconnected: {e}");
|
|
}
|
|
_ => {
|
|
debug!("XMPP Event not supported")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn receive(&mut self, mut rx: mpsc::UnboundedReceiver<Hook>) {
|
|
loop {
|
|
tokio::select! {
|
|
_ = ctrl_c() => {
|
|
return; // Disconnecting
|
|
},
|
|
_ = self.next() => (),
|
|
wh = rx.recv() => {
|
|
if let Some(hook) = wh {
|
|
debug!("XMPP Bot Received Hook");
|
|
self.hook(hook).await
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn hook(&mut self, wh: Hook) {
|
|
debug!("XMPP Bot Processing Hook");
|
|
if let Some(display) = format_hook(&wh) {
|
|
debug!("Hook: {}", display);
|
|
for room in &self.rooms {
|
|
self.agent
|
|
.send_raw_message(RawMessageSettings {
|
|
recipient: Jid::from(room.clone()),
|
|
message_type: MessageType::Groupchat,
|
|
message: &display,
|
|
lang: Some("en"),
|
|
payloads: Vec::new(),
|
|
})
|
|
.await
|
|
}
|
|
debug!("XMPP Bot Processed Hook");
|
|
}
|
|
}
|
|
|
|
pub async fn disconnect(self) -> Result<(), Error> {
|
|
log::info!("Disconnecting...");
|
|
Ok(self.agent.disconnect().await?)
|
|
}
|
|
}
|