Created
April 5, 2018 23:35
-
-
Save PurpleMyst/745922dacca7a4ef125aaf12b353d803 to your computer and use it in GitHub Desktop.
A factoid bot written in Rust.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env run-cargo-script | |
//! A factoid bot written in Rust, using the irc library. | |
//! This bot is written to showcase the irc library, however it might also be useful. | |
//! | |
//! To utilize, create a `factoid_config.json` file in your working directory defining at least | |
//! nickname, server and channels. | |
//! | |
//! If you want some useful logging, you can set the `RUST_LOG` environment variable equal to | |
//! `factoid_bot=info`. | |
//! | |
//! | |
//! ```cargo | |
//! [package] | |
//! name = "factoid_bot" | |
//! version = "1.0.0" | |
//! | |
//! [dependencies] | |
//! irc={ version = "0.13.5", features = ["json"] } | |
//! log="0.4.1" | |
//! env_logger="0.5.6" | |
//! ``` | |
use std::collections::HashMap; | |
extern crate irc; | |
use irc::client::prelude::*; | |
#[macro_use] | |
extern crate log; | |
extern crate env_logger; | |
type IrcResult<T> = irc::error::Result<T>; | |
struct FactoidBot { | |
client: IrcClient, | |
factoids: HashMap<String, String>, | |
} | |
macro_rules! split_once_on_space { | |
($string:ident) => { | |
match $string.find(' ') { | |
Some(space_location) => { | |
let (a, b) = $string.split_at(space_location); | |
(a, &b[1..]) | |
} | |
None => ($string, ""), | |
} | |
}; | |
} | |
impl FactoidBot { | |
fn new(config: Config) -> IrcResult<Self> { | |
let client = IrcClient::from_config(config)?; | |
client.identify()?; | |
info!("Connected."); | |
Ok(Self { | |
client, | |
factoids: HashMap::new(), | |
}) | |
} | |
fn run(mut self) -> IrcResult<()> { | |
self.client | |
.stream() | |
.for_each(|message| self.handle_message(message)) | |
.wait() | |
} | |
fn handle_message(&mut self, message: Message) -> IrcResult<()> { | |
debug!("Got message {:?}", message); | |
if let Command::PRIVMSG(_, ref text) = message.command { | |
if !text.starts_with('$') { | |
// this isn't a factoid, let's just return | |
return Ok(()); | |
} | |
let text = &text[1..]; | |
let response_target = message.response_target().unwrap(); | |
let (factoid, args) = split_once_on_space!(text); | |
info!("Got asked factoid {:?}", factoid); | |
match factoid { | |
"defact" => { | |
let (trigger, response) = split_once_on_space!(args); | |
let source_nickname = message.source_nickname().unwrap(); | |
self.factoids | |
.insert(trigger.to_owned(), response.to_owned()); | |
self.client.send_privmsg( | |
response_target, | |
&format!("{}: Defined factoid {:?}", source_nickname, trigger), | |
)?; | |
} | |
"factoids" => { | |
let factoid_names: String = if self.factoids.is_empty() { | |
"No factoids defined.".to_owned() | |
} else { | |
self.factoids | |
.keys() | |
.map(|key: &String| key as &str) | |
.collect::<Vec<&str>>() | |
.join(" ") | |
}; | |
info!("We have factoids: {:?}", factoid_names); | |
self.client.send_privmsg(response_target, &factoid_names)?; | |
} | |
"at" => { | |
let (target, factoid) = split_once_on_space!(args); | |
if let Some(response) = self.factoids.get(factoid) { | |
info!("Replying with {:?}, but to {:?}", response, target); | |
self.client | |
.send_privmsg(response_target, &format!("{}: {}", target, response))?; | |
} else { | |
info!("That factoid is unknown."); | |
self.client | |
.send_privmsg(response_target, "Unknown factoid.")?; | |
} | |
} | |
_ => { | |
if let Some(response) = self.factoids.get(factoid) { | |
info!("Replying with {:?}", response); | |
self.client.send_privmsg(response_target, response)?; | |
} else { | |
info!("That factoid is unknown."); | |
self.client | |
.send_privmsg(response_target, "Unknown factoid.")?; | |
} | |
} | |
} | |
} | |
Ok(()) | |
} | |
} | |
fn main() { | |
env_logger::init(); | |
Config::load("factoid_config.json") | |
.and_then(|config| FactoidBot::new(config)) | |
.and_then(|bot| bot.run()) | |
.unwrap() | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nickname": "rs-factoid-bot", | |
"server": "chat.freenode.net", | |
"channels": ["#8banana-bottest"] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment