85 lines
2.4 KiB
Rust
85 lines
2.4 KiB
Rust
use async_trait::async_trait;
|
|
use futures::StreamExt;
|
|
use irc::{client::{Client, prelude::Config}, proto::{Command, Message}};
|
|
use log::debug;
|
|
use serde::Deserialize;
|
|
use tokio::select;
|
|
|
|
use crate::{supervisor::{Id, TaskResult, Sender, Task, Receiver}, linkmap::Linkmap};
|
|
use crate::supervisor::Message as BMessage;
|
|
|
|
use super::IrcConfig;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub struct IrcTask {
|
|
config: IrcConfig,
|
|
links: Linkmap<String>,
|
|
}
|
|
|
|
impl IrcTask {
|
|
async fn handle_bridge_msg(&self, id: Id, client: &mut Client, msg: BMessage) -> TaskResult {
|
|
for channel in self.links.get_channels(&msg.link) {
|
|
if msg.origin.0 == id && &msg.origin.1 == channel {
|
|
continue
|
|
}
|
|
|
|
debug!("{id}: bridging message from {:?}/{:?} to {channel:?}", msg.origin, msg.link);
|
|
client.send_privmsg(channel, format!("<{}> {}", msg.author, msg.content))?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
async fn handle_irc_msg(&self, id: Id, tx: &mut Sender, msg: Message) -> TaskResult {
|
|
if let Command::PRIVMSG(channel, message) = &msg.command {
|
|
|
|
let Some(link) = self.links.get_link(channel) else { return Ok(()) };
|
|
let Some(author) = msg.source_nickname() else { return Ok(()) };
|
|
|
|
debug!("{id}: broadcasting message from {:?} to {:?}", channel, link);
|
|
tx.send(BMessage {
|
|
origin: (id, channel.clone()),
|
|
link: link.clone(),
|
|
author: author.to_owned(),
|
|
suffix: self.config.suffix.clone(),
|
|
content: message.clone(),
|
|
avatar: None,
|
|
})?;
|
|
}
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[async_trait]
|
|
impl Task for IrcTask {
|
|
async fn start(&self, id: Id, mut tx: Sender, mut rx: Receiver) -> TaskResult {
|
|
let config = Config {
|
|
server: Some(self.config.server.clone()),
|
|
port: Some(self.config.port),
|
|
nickname: Some(self.config.nick.clone()),
|
|
alt_nicks: self.config.alt_nicks.clone(),
|
|
use_tls: Some(self.config.tls),
|
|
channels: self.links.iter_channels().cloned().collect(),
|
|
..Config::default()
|
|
};
|
|
|
|
debug!("{id}: building IRC client");
|
|
let mut client = Client::from_config(config).await?;
|
|
|
|
debug!("{id}: identifying");
|
|
client.identify()?;
|
|
let mut stream = client.stream()?;
|
|
|
|
debug!("{id}: entering event loop");
|
|
|
|
loop {
|
|
select! {
|
|
bridge_msg = rx.recv() => self.handle_bridge_msg(id, &mut client, bridge_msg?).await?,
|
|
irc_msg = stream.next() => match irc_msg {
|
|
Some(msg) => self.handle_irc_msg(id, &mut tx, msg?).await?,
|
|
None => return Err("Lost connection to IRC server".into()),
|
|
}
|
|
};
|
|
}
|
|
}
|
|
}
|