Skip to content

Instantly share code, notes, and snippets.

@PurpleMyst
Created April 5, 2018 23:35
Show Gist options
  • Save PurpleMyst/745922dacca7a4ef125aaf12b353d803 to your computer and use it in GitHub Desktop.
Save PurpleMyst/745922dacca7a4ef125aaf12b353d803 to your computer and use it in GitHub Desktop.
A factoid bot written in Rust.
#!/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()
}
{
"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