ManifoldConfig rework
This commit is contained in:
parent
33a66e3cff
commit
abdcc07fe2
|
|
@ -12,6 +12,7 @@ built = { version = "0.5.1", features = ["git2", "chrono"] }
|
|||
[dependencies]
|
||||
built = { version = "0.5.1", features = ["git2", "chrono"] }
|
||||
clap = "3.2.10"
|
||||
config = { version = "0.13.1", features = [ "yaml" ] }
|
||||
diesel = { version = "1.4.8", features = ["sqlite", "r2d2", "chrono"] }
|
||||
diesel_migrations = "1.4.0"
|
||||
env_logger = "0.9.0"
|
||||
|
|
|
|||
126
src/config.rs
126
src/config.rs
|
|
@ -1,125 +1,65 @@
|
|||
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;
|
||||
use config::Config;
|
||||
use serenity::model::prelude::{ChannelId, MessageId, RoleId};
|
||||
use crate::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;
|
||||
pub environment: String,
|
||||
pub path: PathBuf,
|
||||
pub config: Config,
|
||||
}
|
||||
|
||||
impl ManifoldConfig {
|
||||
pub fn new() -> Self {
|
||||
ManifoldConfig {
|
||||
config_path: Default::default(),
|
||||
config_environment: "Production".to_string(),
|
||||
config: HashMap::<String, String>::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
pub fn load_config(config_file: &String, bot_environment: &String) -> ManifoldResult<Self> {
|
||||
|
||||
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 settings = Config::builder()
|
||||
.set_override("BotEnvironment", bot_environment.clone())?
|
||||
.add_source(config::File::with_name(config_file))
|
||||
.add_source(config::Environment::with_prefix("MANIFOLD"))
|
||||
.build()?;
|
||||
|
||||
let config_entry_count = self.config.len();
|
||||
|
||||
debug!("Loaded config: {:?}", &self.config);
|
||||
debug!("Loaded {} entries", config_entry_count);
|
||||
|
||||
Ok(config_entry_count)
|
||||
Ok(Self {
|
||||
environment: bot_environment.clone(),
|
||||
path: PathBuf::from(config_file),
|
||||
config: settings
|
||||
})
|
||||
}
|
||||
|
||||
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)
|
||||
pub fn get_environment(&self) -> &String {
|
||||
&self.environment
|
||||
}
|
||||
|
||||
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()
|
||||
pub fn get_path(&self) -> &PathBuf {
|
||||
&self.path
|
||||
}
|
||||
|
||||
fn get_environment(&self) -> &String {
|
||||
&self.config_environment
|
||||
pub fn get_environment_mut(&mut self) -> &mut String {
|
||||
&mut self.environment
|
||||
}
|
||||
|
||||
fn get_path(&self) -> &PathBuf {
|
||||
&self.config_path
|
||||
pub fn get_path_mut(&mut self) -> &mut PathBuf {
|
||||
&mut self.path
|
||||
}
|
||||
|
||||
fn get_environment_mut(&mut self) -> &mut String {
|
||||
&mut self.config_environment
|
||||
pub fn get_value(&self, key: &String) -> ManifoldResult<String> {
|
||||
Ok(self.config.get_string(&format!("{}{}", &self.environment, key))?)
|
||||
}
|
||||
|
||||
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 {
|
||||
pub fn get_role(&self, role_name: &String) -> ManifoldResult<RoleId> {
|
||||
let key = format!("{}Role", role_name);
|
||||
|
||||
RoleId(self.get_value(&key).unwrap().parse::<u64>().unwrap())
|
||||
Ok(RoleId(self.get_value(&key)?.parse::<u64>()?))
|
||||
}
|
||||
|
||||
fn get_channel(&self, channel_name: &String) -> ChannelId {
|
||||
pub fn get_channel(&self, channel_name: &String) -> ManifoldResult<ChannelId> {
|
||||
let key = format!("{}Channel", channel_name);
|
||||
|
||||
ChannelId(self.get_value(&key).unwrap().parse::<u64>().unwrap())
|
||||
Ok(ChannelId(self.get_value(&key)?.parse::<u64>()?))
|
||||
}
|
||||
|
||||
fn get_message(&self, message_id: &String) -> MessageId {
|
||||
pub fn get_message(&self, message_id: &String) -> ManifoldResult<MessageId> {
|
||||
let key = format!("{}Message", message_id);
|
||||
|
||||
MessageId(self.get_value(&key).unwrap().parse::<u64>().unwrap())
|
||||
Ok(MessageId(self.get_value(&key)?.parse::<u64>()?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,8 @@ use serenity::{
|
|||
},
|
||||
model::prelude::*
|
||||
};
|
||||
use crate::config::{Config, ManifoldConfig};
|
||||
|
||||
use crate::ManifoldConfig;
|
||||
use crate::built_info;
|
||||
|
||||
#[command]
|
||||
|
|
@ -57,8 +58,8 @@ async fn get_config(ctx: &Context, msg: &Message, mut args: Args) -> CommandResu
|
|||
};
|
||||
|
||||
let value = match config.get_value(&key) {
|
||||
Some(v) => v.clone(),
|
||||
None => "not found, sorry!".to_string()
|
||||
Ok(v) => v.clone(),
|
||||
Err(_) => "not found, sorry!".to_string()
|
||||
};
|
||||
|
||||
msg.reply_ping(&ctx, format!("Value for key {} was {}", &key, &value)).await?;
|
||||
|
|
@ -84,13 +85,11 @@ async fn set_config(ctx: &Context, msg: &Message, mut args: Args) -> CommandResu
|
|||
Err(e) => { msg.reply_ping(&ctx, format!("Error parsing your message: {:?}", e)).await?; Err("ArgParse")? }
|
||||
};
|
||||
|
||||
match config.set_value(&key, &value) {
|
||||
Some(_) => msg.reply_ping(&ctx, format!("Value for key {} set to {}", &key, &value)).await?,
|
||||
None => msg.reply_ping(&ctx, format!("Error setting config value")).await?,
|
||||
match config.config.set(&key, value.clone()) {
|
||||
Ok(_) => msg.reply_ping(&ctx, format!("Value for key {} set to {}", &key, &value)).await?,
|
||||
Err(_) => msg.reply_ping(&ctx, format!("Error setting config value")).await?,
|
||||
};
|
||||
|
||||
config.save_config()?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
|||
10
src/error.rs
10
src/error.rs
|
|
@ -1,5 +1,7 @@
|
|||
use std::error::Error;
|
||||
use std::fmt;
|
||||
use std::num::ParseIntError;
|
||||
use config::ConfigError;
|
||||
use serenity::prelude::SerenityError;
|
||||
use reqwest::Error as ReqwestError;
|
||||
|
||||
|
|
@ -77,3 +79,11 @@ impl From<ReqwestError> for ManifoldError {
|
|||
ManifoldError::new(&err.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ConfigError> for ManifoldError {
|
||||
fn from(err: ConfigError) -> Self { ManifoldError::new(&err.to_string()) }
|
||||
}
|
||||
|
||||
impl From<ParseIntError> for ManifoldError {
|
||||
fn from(err: ParseIntError) -> Self { ManifoldError::new(&err.to_string()) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use serenity::model::{
|
|||
id::ChannelId,
|
||||
};
|
||||
use serenity::prelude::{Context, EventHandler};
|
||||
use crate::config::{Config, ManifoldConfig};
|
||||
use crate::ManifoldConfig;
|
||||
|
||||
use crate::responses::Responses;
|
||||
|
||||
|
|
@ -38,10 +38,10 @@ impl Handler {
|
|||
None => "Manifold bot connected to discord and ready to begin broadcast operations.".to_string(),
|
||||
};
|
||||
|
||||
let bot_nickname = config.get_value(&"BotNickname".to_string()).map(|n| n.as_str());
|
||||
let channel: ChannelId = config.get_channel(&"Log".to_string());
|
||||
let bot_nickname = config.get_value(&"BotNickname".to_string()).unwrap_or("BrokenManifoldBot".to_string());
|
||||
let channel: ChannelId = config.get_channel(&"Log".to_string()).expect("Specified log channel invalid or unavailable");
|
||||
for guild in data_about_bot.guilds {
|
||||
match guild.id.edit_nickname(&ctx, bot_nickname).await {
|
||||
match guild.id.edit_nickname(&ctx, Some(&*bot_nickname)).await {
|
||||
Ok(()) => (),
|
||||
Err(e) => {
|
||||
error!("Error setting bot nickname (lack permission?): {:?}", e);
|
||||
|
|
|
|||
46
src/lib.rs
46
src/lib.rs
|
|
@ -3,18 +3,18 @@
|
|||
|
||||
use std::collections::HashSet;
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::ops::Deref;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use clap::ArgMatches;
|
||||
use diesel::r2d2::{ConnectionManager};
|
||||
use diesel::SqliteConnection;
|
||||
use crate::config::{Config, ManifoldConfig};
|
||||
use serenity::prelude::*;
|
||||
use serenity::framework::standard::{*, macros::*};
|
||||
use serenity::http::Http;
|
||||
use serenity::model::prelude::{GuildId, Message, UserId};
|
||||
use crate::config::ManifoldConfig;
|
||||
|
||||
use crate::error::ManifoldResult;
|
||||
use crate::responses::Responses;
|
||||
|
||||
|
|
@ -63,27 +63,13 @@ struct Core;
|
|||
|
||||
pub async fn prepare_client<T: 'static + EventHandler>(arguments: ArgMatches, mut framework: StandardFramework, event_handler: T, intents: GatewayIntents) -> ManifoldResult<Client> {
|
||||
let bot_environment = arguments.value_of("environment").unwrap_or("Production").to_string();
|
||||
let config_file = format!("config/{}", arguments.value_of("config-file").unwrap_or("manifold.json"));
|
||||
if arguments.occurrences_of("make-config") > 0 {
|
||||
if File::open(&config_file).is_ok() {
|
||||
warn!("Not making a new configuration file - configuration exists at {}. Please remove this if you want to generate a fresh config, or provide an alternative path.", &config_file);
|
||||
Err("ConfigExists")?
|
||||
} else {
|
||||
let config = ManifoldConfig::new();
|
||||
match config.create_default_config(&config_file, &bot_environment) {
|
||||
Ok(_) => warn!("Writing new configuration to {}", &config_file),
|
||||
Err(e) => {error!("Could not write new config! {}", e.details); Err(e)?}
|
||||
}
|
||||
}
|
||||
Err("MadeConfig")?
|
||||
}
|
||||
let config_file = format!("config/{}", arguments.value_of("config-file").unwrap_or("manifold.yaml"));
|
||||
|
||||
info!("Reading configuration...");
|
||||
debug!("Configuration file path: {}", &config_file);
|
||||
let config = load_config(&config_file, &bot_environment);
|
||||
debug!("Current configuration: {:?}", &config);
|
||||
let config = ManifoldConfig::load_config(&config_file, &bot_environment).expect(&*format!("Could not read configuration file {}", &config_file));
|
||||
|
||||
let prefix = config.get_value(&"BotPrefix".to_string()).unwrap();
|
||||
let prefix = config.get_value(&"BotPrefix".to_string()).expect("Could not read bot_prefix from config.");
|
||||
|
||||
let manager = ConnectionManager::<SqliteConnection>::new("manifold.db");
|
||||
let pool = r2d2::Pool::builder()
|
||||
|
|
@ -92,7 +78,7 @@ pub async fn prepare_client<T: 'static + EventHandler>(arguments: ArgMatches, mu
|
|||
.expect("Database setup error!");
|
||||
|
||||
let mut responses = Responses::new();
|
||||
responses.reload(&PathBuf::from(config.get_value(&"ResponsesFilePath".to_string()).unwrap_or(&"txt/responses.txt".to_string()))).expect("Could not load responses file!");
|
||||
responses.reload(&PathBuf::from(config.get_value(&"ResponsesFilePath".to_string()).unwrap_or("txt/responses.txt".to_string()))).expect("Could not load responses file!");
|
||||
|
||||
|
||||
let token = env::var("DISCORD_TOKEN").expect(
|
||||
|
|
@ -142,14 +128,6 @@ pub async fn prepare_client<T: 'static + EventHandler>(arguments: ArgMatches, mu
|
|||
Ok(client)
|
||||
}
|
||||
|
||||
fn load_config(config_file: &String, bot_environment: &String) -> ManifoldConfig {
|
||||
let mut config = ManifoldConfig::new();
|
||||
*config.get_path_mut() = PathBuf::from(config_file);
|
||||
*config.get_environment_mut() = bot_environment.to_owned();
|
||||
config.load_config().expect("Could not load config - halting");
|
||||
config
|
||||
}
|
||||
|
||||
#[help]
|
||||
async fn manifold_help(
|
||||
ctx: &Context,
|
||||
|
|
@ -173,8 +151,8 @@ async fn mod_or_higher_check(ctx: &Context, msg: &Message, _: &mut Args, _: &Com
|
|||
};
|
||||
|
||||
let role_guild_config = match config.get_value(&"RoleGuild".to_string()) {
|
||||
Some(rgc) => rgc,
|
||||
None => {
|
||||
Ok(rgc) => rgc,
|
||||
Err(_) => {
|
||||
error!("Guild not configured");
|
||||
return Err(Reason::Unknown);
|
||||
}
|
||||
|
|
@ -189,7 +167,13 @@ async fn mod_or_higher_check(ctx: &Context, msg: &Message, _: &mut Args, _: &Com
|
|||
};
|
||||
|
||||
let guild_id = GuildId(role_guild_number);
|
||||
let administrator_role = config.get_role(&"Admin".to_string());
|
||||
let administrator_role = match config.get_role(&"Admin".to_string()) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
error!("Get admin role from config failed: {:?}", e);
|
||||
return Err(Reason::Log(e.to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
if !msg.author.has_role(&ctx, guild_id, administrator_role).await.unwrap_or(false) {
|
||||
return Err(Reason::User("User not administrative".to_string()));
|
||||
|
|
|
|||
Loading…
Reference in New Issue