mirror of
https://gitea.mizah.xyz/mizah/dergchat
synced 2024-11-27 10:22:16 -05:00
128 lines
4.6 KiB
Rust
128 lines
4.6 KiB
Rust
|
use crate::types::{LoginCredentials, Message};
|
||
|
use dioxus::hooks::{UnboundedReceiver, UseRef};
|
||
|
use futures_util::stream::StreamExt;
|
||
|
use jid::BareJid;
|
||
|
use log::{error, info};
|
||
|
use std::collections::HashMap;
|
||
|
use std::future::Future;
|
||
|
use std::str::FromStr;
|
||
|
use tokio::select;
|
||
|
use xmpp::parsers::message::MessageType;
|
||
|
use xmpp::{Agent, ClientBuilder, ClientType};
|
||
|
|
||
|
async fn handle_event(
|
||
|
event: xmpp::Event,
|
||
|
agent: &mut xmpp::Agent,
|
||
|
messages: &mut UseRef<HashMap<BareJid, Vec<Message>>>,
|
||
|
) {
|
||
|
match event {
|
||
|
xmpp::Event::JoinRoom(jid, conference) => {
|
||
|
println!("Will auto-join room: {}", &jid);
|
||
|
agent.join_room(jid, None, None, "en/us", "online").await;
|
||
|
}
|
||
|
xmpp::Event::RoomJoined(room_jid) => {
|
||
|
println!("Joined room: {}", &room_jid);
|
||
|
messages.with_mut(move |m| {
|
||
|
m.entry(room_jid.clone()).or_insert(vec![]);
|
||
|
});
|
||
|
}
|
||
|
xmpp::Event::RoomLeft(room_jid) => {
|
||
|
println!("Left room: {}", &room_jid);
|
||
|
messages.with_mut(move |m| {
|
||
|
m.remove(&room_jid);
|
||
|
});
|
||
|
}
|
||
|
xmpp::Event::ChatMessage(id, sender, body) => {
|
||
|
println!("Message from {}: {}", &sender, &body.0);
|
||
|
messages.with_mut(move |m| {
|
||
|
m.entry(sender.clone()).or_insert(vec![]).push(Message {
|
||
|
sender: sender.to_string(),
|
||
|
body: body.0,
|
||
|
});
|
||
|
});
|
||
|
}
|
||
|
xmpp::Event::RoomMessage(id, room_jid, sender_nick, body) => {
|
||
|
println!(
|
||
|
"Message in {} from {}: {}",
|
||
|
&room_jid, &sender_nick, &body.0
|
||
|
);
|
||
|
messages.with_mut(move |m| {
|
||
|
m.entry(room_jid.clone()).or_insert(vec![]).push(Message {
|
||
|
sender: sender_nick,
|
||
|
body: body.0,
|
||
|
})
|
||
|
});
|
||
|
}
|
||
|
xmpp::Event::RoomPrivateMessage(id, room_jid, sender_nick, body) => {
|
||
|
println!(
|
||
|
"Private message in {} from {}: {}",
|
||
|
&room_jid, &sender_nick, &body.0
|
||
|
);
|
||
|
messages.with_mut(move |m| {
|
||
|
m.entry(room_jid.clone()).or_insert(vec![]).push(Message {
|
||
|
sender: sender_nick,
|
||
|
body: body.0,
|
||
|
})
|
||
|
});
|
||
|
}
|
||
|
_ => {
|
||
|
log::debug!("Received unsupported event {:?}", event);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#[derive(Debug)]
|
||
|
pub enum NetworkCommand {
|
||
|
TryLogin { credentials: LoginCredentials },
|
||
|
JoinRoom { room: BareJid },
|
||
|
LeaveRoom { room: BareJid },
|
||
|
SendMessage { recipient: BareJid, message: String },
|
||
|
}
|
||
|
|
||
|
pub fn xmpp_mainloop<'a>(
|
||
|
agent: &'a mut Agent,
|
||
|
mut room_data: &'a mut UseRef<HashMap<BareJid, Vec<Message>>>,
|
||
|
commands: &'a mut UnboundedReceiver<NetworkCommand>,
|
||
|
) -> impl Future<Output = ()> + Sized + 'a {
|
||
|
async move {
|
||
|
loop {
|
||
|
select! {
|
||
|
events = agent.wait_for_events() => {
|
||
|
if let Some(events) = events {
|
||
|
for event in events {
|
||
|
handle_event(event, agent, &mut room_data).await;
|
||
|
}
|
||
|
} else {
|
||
|
info!("Disconnected");
|
||
|
}
|
||
|
},
|
||
|
command = commands.next() => {
|
||
|
if let Some(command) = command {
|
||
|
match command {
|
||
|
NetworkCommand::JoinRoom { room } => {
|
||
|
agent.join_room(room.clone(), None, None, "en-us", "online").await;
|
||
|
},
|
||
|
NetworkCommand::LeaveRoom { room } => {
|
||
|
agent.leave_room(
|
||
|
room,
|
||
|
"dergchat".to_string(),
|
||
|
"en-us",
|
||
|
"User left the room.").await;
|
||
|
},
|
||
|
NetworkCommand::SendMessage { recipient, message } => {
|
||
|
agent.send_message(recipient.into(), MessageType::Groupchat, "en-us", &message).await;
|
||
|
},
|
||
|
NetworkCommand::TryLogin { credentials } => {
|
||
|
panic!("Already logged in.");
|
||
|
},
|
||
|
}
|
||
|
} else {
|
||
|
info!("Command channel closed");
|
||
|
break;
|
||
|
}
|
||
|
},
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|