add a rudimentary irc module
This commit is contained in:
parent
906b5709d0
commit
c6dc3f15b8
@ -16,6 +16,8 @@ time = "0.1"
|
||||
regex = "0.2"
|
||||
multimap = "0.4.0"
|
||||
notify = "4.0.0"
|
||||
irc = "0.11.8" # latest version which supports old openssl version (required by discord)
|
||||
thread_local = "0.3"
|
||||
pvn = { git = "http://gitlab.monarch-pass.net/malacoda/pvn.git" }
|
||||
echobox = { git = "http://gitlab.monarch-pass.net/malacoda/echobox.git" }
|
||||
stc = { git = "http://gitlab.monarch-pass.net/malacoda/stc.git" }
|
||||
|
@ -8,6 +8,8 @@ extern crate transformable_channels;
|
||||
extern crate stc;
|
||||
extern crate regex;
|
||||
extern crate multimap;
|
||||
extern crate irc;
|
||||
extern crate thread_local;
|
||||
|
||||
#[macro_use]
|
||||
extern crate hlua;
|
||||
|
154
src/modules/irc.rs
Normal file
154
src/modules/irc.rs
Normal file
@ -0,0 +1,154 @@
|
||||
use irc::client::prelude::*;
|
||||
use irc::client::data::command::Command;
|
||||
|
||||
use modules::EventLoop;
|
||||
use toml::value::Table;
|
||||
|
||||
use event;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::mpsc::Receiver;
|
||||
use transformable_channels::mpsc::ExtSender;
|
||||
|
||||
use std::fmt;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
|
||||
use crossbeam;
|
||||
|
||||
use thread_local::CachedThreadLocal;
|
||||
use {MessageSender, Message, User, Channel};
|
||||
|
||||
pub struct IrcHandler {
|
||||
config: Config
|
||||
}
|
||||
|
||||
const DEFAULT_NICK: &'static str = "tenquestionmarks";
|
||||
|
||||
impl IrcHandler {
|
||||
pub fn new (_: &Table, configuration: &Table) -> Box<EventLoop> {
|
||||
Box::new(IrcHandler {
|
||||
config: Config {
|
||||
nickname: Some(configuration.get("nickname")
|
||||
.and_then(|value| value.as_str())
|
||||
.unwrap_or(DEFAULT_NICK)
|
||||
.to_owned()),
|
||||
server: Some(configuration.get("server")
|
||||
.and_then(|value| value.as_str())
|
||||
.expect("Expected server in IRC config")
|
||||
.to_owned()),
|
||||
channels: Some(configuration.get("channels")
|
||||
.and_then(|value| value.as_array())
|
||||
.map(|value| value.to_vec())
|
||||
.unwrap_or(vec![])
|
||||
.into_iter()
|
||||
.map(|value| { String::from(value.as_str().unwrap()) })
|
||||
.collect()),
|
||||
.. Default::default()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct IrcMessageSender {
|
||||
irc: IrcServerWrapper,
|
||||
channel: String
|
||||
}
|
||||
|
||||
impl MessageSender for IrcMessageSender {
|
||||
fn send_message (&self, message: &str) {
|
||||
debug!("Send message to channel {:?}: {:?}", self.channel, message);
|
||||
match self.irc.get().send_privmsg(&self.channel, message) {
|
||||
Ok(_) => { debug!("Send message succeeded"); },
|
||||
Err(err) => { error!("Send message failed: {:?}", err) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for IrcMessageSender {
|
||||
fn fmt (&self, formatter: &mut Formatter) -> fmt::Result {
|
||||
write!(formatter, "IrcMessageSender {{ channel: {:?} }}", self.channel)
|
||||
}
|
||||
}
|
||||
|
||||
fn make_user (prefix: &Option<String>, server: &IrcServer) -> Option<User> {
|
||||
prefix.as_ref().and_then(|prefix| prefix.split("!").next()).map(|name| User {
|
||||
name: name.to_owned(),
|
||||
sender: Box::new(IrcMessageSender {
|
||||
irc: IrcServerWrapper::new(&server),
|
||||
channel: name.to_owned()
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
struct IrcServerWrapper {
|
||||
server: IrcServer,
|
||||
thread_local: CachedThreadLocal<IrcServer>
|
||||
}
|
||||
|
||||
impl IrcServerWrapper {
|
||||
pub fn new (server: &IrcServer) -> IrcServerWrapper {
|
||||
IrcServerWrapper {
|
||||
server: server.clone(),
|
||||
thread_local: CachedThreadLocal::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get (&self) -> &IrcServer {
|
||||
self.thread_local.get_or(|| Box::new(self.server.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl Sync for IrcServerWrapper {}
|
||||
|
||||
impl EventLoop for IrcHandler {
|
||||
fn run (&self, sender: Box<ExtSender<event::Event>>, receiver: Receiver<Arc<event::Envelope>>) {
|
||||
let server = IrcServer::from_config(self.config.clone()).unwrap();
|
||||
server.identify().unwrap();
|
||||
|
||||
crossbeam::scope(|scope| {
|
||||
let server_sender = server.clone();
|
||||
scope.spawn(move || {
|
||||
loop {
|
||||
if let Ok(envelope) = receiver.recv() {
|
||||
if let event::Event::Message { ref message } = envelope.event {
|
||||
if let Some(ref channel) = message.channel {
|
||||
server_sender.send_privmsg(&channel.name, &message.content);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
for server_message in server.iter() {
|
||||
if let Ok(irc_message) = server_message {
|
||||
match irc_message.command {
|
||||
Command::PRIVMSG(channel, message) => {
|
||||
if let Some(author) = make_user(&irc_message.prefix, &server) {
|
||||
let message = Message {
|
||||
author: author,
|
||||
content: message,
|
||||
channel: Some(Channel {
|
||||
name: channel.clone(),
|
||||
description: "".to_owned(),
|
||||
topic: "".to_owned(),
|
||||
sender: Box::new(IrcMessageSender {
|
||||
irc: IrcServerWrapper::new(&server),
|
||||
channel: channel.clone()
|
||||
})
|
||||
})
|
||||
};
|
||||
|
||||
if let Err(err) = sender.send(event::Event::Message { message: message }) {
|
||||
error!("Error sending message event: {:?}", err)
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -14,6 +14,7 @@ use modules::pvn::PvnModule;
|
||||
use modules::echobox::EchoboxModule;
|
||||
use modules::autolink::AutolinkModule;
|
||||
use modules::logger::LoggerModule;
|
||||
use modules::irc::IrcHandler;
|
||||
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
@ -33,6 +34,7 @@ impl ModuleLoader {
|
||||
types.insert("echobox", EchoboxModule::new as fn(&Table, &Table) -> Box<EventLoop>);
|
||||
types.insert("autolink", AutolinkModule::new as fn(&Table, &Table) -> Box<EventLoop>);
|
||||
types.insert("logger", LoggerModule::new as fn(&Table, &Table) -> Box<EventLoop>);
|
||||
types.insert("irc", IrcHandler::new as fn(&Table, &Table) -> Box<EventLoop>);
|
||||
ModuleLoader {
|
||||
types: types
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ pub mod pvn;
|
||||
pub mod echobox;
|
||||
pub mod autolink;
|
||||
pub mod logger;
|
||||
pub mod irc;
|
||||
|
||||
pub mod loader;
|
||||
|
||||
|
@ -1,18 +1,22 @@
|
||||
[general]
|
||||
foo = "bar"
|
||||
|
||||
[irc]
|
||||
server = "irc.rizon.net"
|
||||
channels = ["#eightbar"]
|
||||
|
||||
[discord]
|
||||
token = "your token here"
|
||||
|
||||
[stdin]
|
||||
|
||||
[echo]
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
prefix = "?echo"
|
||||
|
||||
[no]
|
||||
type = "random"
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
prefix = "?no"
|
||||
responses = [
|
||||
"https://www.youtube.com/watch?v=WWaLxFIVX1s", # Darth Vader
|
||||
@ -38,7 +42,7 @@ responses = [
|
||||
|
||||
[yes]
|
||||
type = "random"
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
prefix = "?yes"
|
||||
responses = [
|
||||
"https://www.youtube.com/watch?v=JPVaDaynNKM", # Captain Falcon
|
||||
@ -61,15 +65,15 @@ responses = [
|
||||
|
||||
[chk]
|
||||
type = "random"
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
prefix = "?chk"
|
||||
responses = ["ack"]
|
||||
|
||||
[pvn]
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
|
||||
[echobox]
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
|
||||
[lua]
|
||||
parents = ["stdin", "discord"]
|
||||
@ -91,20 +95,20 @@ end
|
||||
"""
|
||||
|
||||
[autolink]
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
|
||||
[logger]
|
||||
parents = ["stdin", "discord"]
|
||||
filters = [{ username = "Dave" }, { username = "Kevin" }]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
#filters = [{ username = "Dave" }, { username = "Kevin" }]
|
||||
|
||||
[icced]
|
||||
type = "random"
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
pattern = "\\bicc?ed?\\b"
|
||||
responses = ["Did some carbon-based lifeform just say **I C E**?"]
|
||||
|
||||
[trout]
|
||||
type = "random"
|
||||
parents = ["stdin", "discord"]
|
||||
parents = ["stdin", "discord", "irc"]
|
||||
pattern = "^?slap (.*)"
|
||||
responses = ["/me slaps $1 around a bit with a large trout", "/me slaps $1 around a bit with a large brick"]
|
||||
|
Loading…
x
Reference in New Issue
Block a user