Initial commit
This commit is contained in:
commit
ad1e0602e3
|
|
@ -0,0 +1,4 @@
|
|||
extern crate built;
|
||||
fn main() {
|
||||
built::write_built_file().expect("Failed to collate build info");
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
use std::collections::HashMap;
|
||||
use std::fs::File;
|
||||
use std::io::{BufReader, BufWriter};
|
||||
use std::path::PathBuf;
|
||||
use serenity::model::prelude::*;
|
||||
use crate::error::ManifoldResult;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ManifoldConfig {
|
||||
config_path: PathBuf,
|
||||
config_environment: String,
|
||||
config: HashMap<String, String>
|
||||
}
|
||||
|
||||
pub trait Config {
|
||||
fn load_config(&mut self) -> ManifoldResult<usize>;
|
||||
fn save_config(&self) -> ManifoldResult<usize>;
|
||||
fn create_default_config(&self, config_file: &String, config_environment: &String) -> ManifoldResult<usize>;
|
||||
fn get_environment(&self) -> &String;
|
||||
fn get_path(&self) -> &PathBuf;
|
||||
fn get_environment_mut(&mut self) -> &mut String;
|
||||
fn get_path_mut(&mut self) -> &mut PathBuf;
|
||||
fn get_value(&self, key: &String) -> Option<&String>;
|
||||
fn set_value(&mut self, key: &String, value: &String) -> Option<String>;
|
||||
fn unset_value(&mut self, key: &String) -> Option<String>;
|
||||
fn get_role(&self, role_name: &String) -> RoleId;
|
||||
fn get_channel(&self, channel_name: &String) -> ChannelId;
|
||||
fn get_message(&self, message_id: &String) -> MessageId;
|
||||
}
|
||||
|
||||
impl ManifoldConfig {
|
||||
pub fn new() -> Self {
|
||||
ManifoldConfig {
|
||||
config_path: Default::default(),
|
||||
config_environment: "Production".to_string(),
|
||||
config: HashMap::<String, String>::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Config for ManifoldConfig {
|
||||
fn load_config(&mut self) -> ManifoldResult<usize> {
|
||||
let file = File::open(&self.config_path).expect("Could not open config file. Please check and retry.");
|
||||
let reader = BufReader::new(file);
|
||||
self.config = serde_json::from_reader(reader)
|
||||
.map_err(|e| {error!("Error reading config as JSON: {:?}", e.to_string()); e} )?;
|
||||
|
||||
let config_entry_count = self.config.len();
|
||||
|
||||
debug!("Loaded config: {:?}", &self.config);
|
||||
debug!("Loaded {} entries", config_entry_count);
|
||||
|
||||
Ok(config_entry_count)
|
||||
}
|
||||
|
||||
fn save_config(&self) -> ManifoldResult<usize> {
|
||||
let file = File::create(&self.config_path).expect("Could not open config file for saving.");
|
||||
let writer = BufWriter::new(file);
|
||||
serde_json::to_writer(writer, &self.config)?;
|
||||
|
||||
let config_entry_count = self.config.len();
|
||||
|
||||
Ok(config_entry_count)
|
||||
}
|
||||
|
||||
fn create_default_config(&self, config_file: &String, config_environment: &String) -> ManifoldResult<usize> {
|
||||
let mut config = ManifoldConfig::new();
|
||||
config.config_environment = config_environment.to_owned();
|
||||
config.config_path = PathBuf::from(config_file);
|
||||
config.config.insert(format!("{}LogChannel", config_environment), "".to_string());
|
||||
config.config.insert(format!("{}BotOwner", config_environment), "".to_string());
|
||||
config.config.insert(format!("{}AdminRole", config_environment), "".to_string());
|
||||
config.config.insert(format!("{}DJRole", config_environment), "".to_string());
|
||||
config.config.insert(format!("{}SpamChannel", config_environment), "true".to_string());
|
||||
config.config.insert(format!("{}ResponsesFilePath", config_environment), "config/responses.txt".to_string());
|
||||
|
||||
config.save_config()
|
||||
}
|
||||
|
||||
fn get_environment(&self) -> &String {
|
||||
&self.config_environment
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &PathBuf {
|
||||
&self.config_path
|
||||
}
|
||||
|
||||
fn get_environment_mut(&mut self) -> &mut String {
|
||||
&mut self.config_environment
|
||||
}
|
||||
|
||||
fn get_path_mut(&mut self) -> &mut PathBuf {
|
||||
&mut self.config_path
|
||||
}
|
||||
|
||||
fn get_value(&self, key: &String) -> Option<&String> {
|
||||
self.config.get(&format!("{}{}", &self.config_environment, key))
|
||||
}
|
||||
|
||||
fn set_value(&mut self, key: &String, value: &String) -> Option<String> {
|
||||
self.config.insert(format!("{}{}", &self.config_environment, key), value.clone())
|
||||
}
|
||||
|
||||
fn unset_value(&mut self, key: &String) -> Option<String> {
|
||||
self.config.remove(&*format!("{}{}", &self.config_environment, key))
|
||||
}
|
||||
|
||||
fn get_role(&self, role_name: &String) -> RoleId {
|
||||
let key = format!("{}Role", role_name);
|
||||
|
||||
RoleId(self.get_value(&key).unwrap().parse::<u64>().unwrap())
|
||||
}
|
||||
|
||||
fn get_channel(&self, channel_name: &String) -> ChannelId {
|
||||
let key = format!("{}Channel", channel_name);
|
||||
|
||||
ChannelId(self.get_value(&key).unwrap().parse::<u64>().unwrap())
|
||||
}
|
||||
|
||||
fn get_message(&self, message_id: &String) -> MessageId {
|
||||
let key = format!("{}Message", message_id);
|
||||
|
||||
MessageId(self.get_value(&key).unwrap().parse::<u64>().unwrap())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use serenity::prelude::SerenityError;
|
||||
|
||||
pub type ManifoldResult<T> = Result<T, ManifoldError>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ManifoldError {
|
||||
pub details: String
|
||||
}
|
||||
|
||||
impl ManifoldError {
|
||||
pub fn new(msg: &str) -> Self {
|
||||
Self {
|
||||
details: msg.to_string()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for ManifoldError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.details)
|
||||
}
|
||||
}
|
||||
|
||||
impl Error for ManifoldError {
|
||||
fn description(&self) -> &str {
|
||||
&self.details
|
||||
}
|
||||
}
|
||||
|
||||
impl From<()> for ManifoldError {
|
||||
fn from(_err: () ) -> Self {
|
||||
ManifoldError::new("Unspecified error")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<r2d2::Error> for ManifoldError {
|
||||
fn from(err: r2d2::Error) -> Self {
|
||||
ManifoldError::new(&err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<std::io::Error> for ManifoldError {
|
||||
fn from(err: std::io::Error) -> Self {
|
||||
ManifoldError::new(&err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<serde_json::error::Error> for ManifoldError {
|
||||
fn from(err: serde_json::error::Error) -> Self {
|
||||
ManifoldError::new(&err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<regex::Error> for ManifoldError {
|
||||
fn from(err: regex::Error) -> Self {
|
||||
ManifoldError::new(&err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ManifoldError {
|
||||
fn from(err: &str) -> Self {
|
||||
ManifoldError::new(&err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SerenityError> for ManifoldError {
|
||||
fn from(err: SerenityError) -> Self {
|
||||
ManifoldError::new(&err.to_string())
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
use std::sync::atomic::AtomicBool;
|
||||
|
||||
use serenity::async_trait;
|
||||
use serenity::model::{
|
||||
gateway::Ready,
|
||||
id::ChannelId,
|
||||
};
|
||||
use serenity::prelude::{Context, EventHandler};
|
||||
use crate::config::{Config, ManifoldConfig};
|
||||
|
||||
use crate::responses::Responses;
|
||||
|
||||
pub struct Handler {
|
||||
timer_running: AtomicBool,
|
||||
}
|
||||
|
||||
impl Handler {
|
||||
pub fn new() -> Self {
|
||||
Handler {
|
||||
timer_running: AtomicBool::from(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl EventHandler for Handler {
|
||||
async fn ready(&self, ctx: Context, _data_about_bot: Ready) {
|
||||
let data = ctx.data.read().await;
|
||||
let config = match data.get::<ManifoldConfig>() {
|
||||
Some(c) => c.lock().await,
|
||||
None => return
|
||||
};
|
||||
|
||||
let responses = match data.get::<Responses>() {
|
||||
Some(r) => r.lock().await,
|
||||
None => return
|
||||
};
|
||||
|
||||
let greeting = match responses.get_response(&"bot startup".to_string()) {
|
||||
Some(g) => g.replace("{NAME}", &*ctx.cache.current_user().await.name).replace("{COFFEE_TYPE}", "espresso").to_string(),
|
||||
None => "Manifold bot connected to discord and ready to begin broadcast operations.".to_string(),
|
||||
};
|
||||
|
||||
let channel: ChannelId = config.get_channel(&"Log".to_string());
|
||||
|
||||
channel.say(&ctx, greeting).await.expect("Couldn't message log channel!");
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::fs::File;
|
||||
|
||||
use regex::Regex;
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
use crate::error::ManifoldResult;
|
||||
use std::io::{BufReader, BufRead};
|
||||
|
||||
pub struct Responses {
|
||||
file_content: HashMap<String, Vec<String>>
|
||||
}
|
||||
|
||||
impl Responses {
|
||||
pub fn new() -> Self {
|
||||
Responses {
|
||||
file_content: HashMap::<String, Vec<String>>::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reload(&mut self, file_path: &PathBuf) -> ManifoldResult<()> {
|
||||
self.file_content = HashMap::<String, Vec<String>>::new();
|
||||
|
||||
let file = File::open(file_path)?;
|
||||
|
||||
let reader = BufReader::new(file);
|
||||
let section_pattern = Regex::new(r"^\[([\w\s]+)]$")?;
|
||||
let mut current_section = "".to_string();
|
||||
let mut last_section_content = Vec::<String>::new();
|
||||
|
||||
for line in reader.lines() {
|
||||
if let Ok(l) = line {
|
||||
debug!("{:?}", &l);
|
||||
if let Some(c) = section_pattern.captures(&*l) {
|
||||
self.file_content.insert(current_section, last_section_content);
|
||||
current_section = c.get(1).unwrap().as_str().to_string();
|
||||
last_section_content = Vec::<String>::new();
|
||||
} else {
|
||||
last_section_content.push(l)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
debug!("{:?}", self.file_content);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_response(&self, section: &String) -> Option<&String> {
|
||||
if let Some(s) = self.file_content.get(section) {
|
||||
s.choose(&mut rand::thread_rng())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue