Added logging to bot
+ Cleaned up error handling to make it easier to handle multiple error levelsmain
parent
199516f3cc
commit
c45bb592db
|
@ -442,11 +442,13 @@ dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"config",
|
"config",
|
||||||
"geoffrey_models",
|
"geoffrey_models",
|
||||||
|
"log",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde 1.0.130",
|
"serde 1.0.130",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_plain",
|
"serde_plain",
|
||||||
"serenity",
|
"serenity",
|
||||||
|
"simple_logger",
|
||||||
"structopt",
|
"structopt",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
@ -471,6 +473,7 @@ name = "geoffrey_models"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
|
"log",
|
||||||
"serde 1.0.130",
|
"serde 1.0.130",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,37 +2,7 @@ use log::{LevelFilter, SetLoggerError};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
use geoffrey_models::logging::LogLevel;
|
||||||
pub enum LogLevel {
|
|
||||||
None,
|
|
||||||
Warn,
|
|
||||||
Info,
|
|
||||||
Debug,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for LogLevel {
|
|
||||||
#[allow(clippy::wildcard_in_or_patterns)]
|
|
||||||
fn from(s: &str) -> Self {
|
|
||||||
let s = s.to_lowercase();
|
|
||||||
match s.as_str() {
|
|
||||||
"warn" | "w" => LogLevel::Warn,
|
|
||||||
"info" | "i" => LogLevel::Info,
|
|
||||||
"debug" | "d" => LogLevel::Debug,
|
|
||||||
"none" | _ => LogLevel::None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<LogLevel> for LevelFilter {
|
|
||||||
fn from(l: LogLevel) -> Self {
|
|
||||||
match l {
|
|
||||||
LogLevel::None => LevelFilter::Off,
|
|
||||||
LogLevel::Warn => LevelFilter::Warn,
|
|
||||||
LogLevel::Info => LevelFilter::Info,
|
|
||||||
LogLevel::Debug => LevelFilter::Debug,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_logging(log_level: LogLevel) -> Result<(), SetLoggerError> {
|
pub fn init_logging(log_level: LogLevel) -> Result<(), SetLoggerError> {
|
||||||
SimpleLogger::new()
|
SimpleLogger::new()
|
||||||
|
|
|
@ -1,24 +1,28 @@
|
||||||
mod commands;
|
|
||||||
mod config;
|
|
||||||
mod context;
|
|
||||||
mod helper;
|
|
||||||
mod logging;
|
|
||||||
|
|
||||||
use crate::commands::add_token::AddToken;
|
|
||||||
use crate::commands::{command_filter, Command};
|
|
||||||
use crate::config::GeoffreyAPIConfig;
|
|
||||||
use crate::context::Context;
|
|
||||||
use crate::logging::{init_logging, LogLevel};
|
|
||||||
use geoffrey_models::models::parameters::add_token_params::AddTokenParams;
|
|
||||||
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
|
||||||
use geoffrey_models::models::token::Permissions;
|
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
use geoffrey_models::logging::LogLevel;
|
||||||
|
use geoffrey_models::models::parameters::add_token_params::AddTokenParams;
|
||||||
|
use geoffrey_models::models::response::api_error::GeoffreyAPIError;
|
||||||
|
use geoffrey_models::models::token::Permissions;
|
||||||
|
|
||||||
|
use crate::commands::{Command, command_filter};
|
||||||
|
use crate::commands::add_token::AddToken;
|
||||||
|
use crate::config::GeoffreyAPIConfig;
|
||||||
|
use crate::context::Context;
|
||||||
|
use crate::logging::init_logging;
|
||||||
|
|
||||||
|
mod commands;
|
||||||
|
mod config;
|
||||||
|
mod context;
|
||||||
|
mod helper;
|
||||||
|
mod logging;
|
||||||
|
|
||||||
pub type Result<T> = std::result::Result<T, GeoffreyAPIError>;
|
pub type Result<T> = std::result::Result<T, GeoffreyAPIError>;
|
||||||
|
|
||||||
#[derive(Debug, StructOpt, Clone)]
|
#[derive(Debug, StructOpt, Clone)]
|
||||||
|
|
|
@ -16,3 +16,5 @@ serde_plain = "1.0.0"
|
||||||
async-trait = "0.1.51"
|
async-trait = "0.1.51"
|
||||||
config = "0.11.0"
|
config = "0.11.0"
|
||||||
structopt = "0.3.21"
|
structopt = "0.3.21"
|
||||||
|
log = "0.4.14"
|
||||||
|
simple_logger = "1.13.0"
|
||||||
|
|
|
@ -98,33 +98,29 @@ pub trait BotCommand {
|
||||||
resp
|
resp
|
||||||
} else {
|
} else {
|
||||||
match err {
|
match err {
|
||||||
CommandError::GeoffreyApi(err) => match err {
|
CommandError::GeoffreyApi(GeoffreyAPIError::PlayerNotRegistered) => {
|
||||||
GeoffreyAPIError::PlayerNotRegistered => {
|
"You need to register before using this command!".to_string()
|
||||||
"You need to register before using this command!".to_string()
|
}
|
||||||
}
|
CommandError::GeoffreyApi(GeoffreyAPIError::EntryNotFound) => {
|
||||||
GeoffreyAPIError::EntryNotFound => {
|
|
||||||
"Couldn't find that, maybe look for something that exists?".to_string()
|
"Couldn't find that, maybe look for something that exists?".to_string()
|
||||||
}
|
}
|
||||||
GeoffreyAPIError::PermissionInsufficient => {
|
CommandError::GeoffreyApi(GeoffreyAPIError::PermissionInsufficient) => {
|
||||||
"Looks like you don't have permission for that.".to_string()
|
"Looks like you don't have permission for that.".to_string()
|
||||||
}
|
}
|
||||||
GeoffreyAPIError::EntryNotUnique => {
|
CommandError::GeoffreyApi(GeoffreyAPIError::EntryNotUnique) => {
|
||||||
"Slow down, I already know that thing. Try a new name.".to_string()
|
"Slow down, I already know that thing. Try a new name.".to_string()
|
||||||
}
|
}
|
||||||
GeoffreyAPIError::DatabaseError(_) => "How the heck u mess that up".to_string(),
|
CommandError::GeoffreyApi(GeoffreyAPIError::MultipleLocationsMatch) => {
|
||||||
GeoffreyAPIError::TokenNotAuthorized => "WHO ARE YOU????".to_string(),
|
"I couldn't match a single location, narrow down your search".to_string()
|
||||||
GeoffreyAPIError::MultipleLocationsMatch => {
|
}
|
||||||
"I couldn't match a single location, narrow down your search".to_string()
|
CommandError::GeoffreyApi(GeoffreyAPIError::ParameterInvalid(err)) => {
|
||||||
}
|
format!(
|
||||||
GeoffreyAPIError::ParameterInvalid(err) => {
|
"Welp, you some how messed up the {} parameter, great job",
|
||||||
format!(
|
err
|
||||||
"Welp, you some how messed up the {} parameter, great job",
|
)
|
||||||
err
|
}
|
||||||
)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => {
|
_ => {
|
||||||
println!("GeoffreyBot got an unhandled error: {}", err);
|
log::warn!("GeoffreyBot got an unhandled error: {}", err);
|
||||||
format!("OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our \
|
format!("OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our \
|
||||||
headquarters are working VEWY HAWD to fix this! (Error in command {})", Self::command_name())
|
headquarters are working VEWY HAWD to fix this! (Error in command {})", Self::command_name())
|
||||||
}
|
}
|
||||||
|
@ -149,6 +145,8 @@ pub trait BotCommand {
|
||||||
) -> Result<String, CommandError> {
|
) -> Result<String, CommandError> {
|
||||||
let mut args = Self::process_arguments(command_interact).await?;
|
let mut args = Self::process_arguments(command_interact).await?;
|
||||||
|
|
||||||
|
log::info!("Running command {}, with args {:?}", Self::command_name(), args);
|
||||||
|
|
||||||
args.set_token(ctx.cfg.api.token.clone());
|
args.set_token(ctx.cfg.api.token.clone());
|
||||||
args.set_user_id(user_id);
|
args.set_user_id(user_id);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
use log::{LevelFilter, SetLoggerError};
|
||||||
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
|
use geoffrey_models::logging::LogLevel;
|
||||||
|
|
||||||
|
pub fn init_logging(log_level: LogLevel) -> Result<(), SetLoggerError> {
|
||||||
|
SimpleLogger::new()
|
||||||
|
.with_level(LevelFilter::Warn)
|
||||||
|
.with_module_level("geoffrey_bot", log_level.into())
|
||||||
|
.init()
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
mod bot;
|
mod bot;
|
||||||
mod configs;
|
mod configs;
|
||||||
mod context;
|
mod context;
|
||||||
|
mod logging;
|
||||||
|
|
||||||
use crate::bot::create_commands;
|
use crate::bot::create_commands;
|
||||||
use crate::configs::GeoffreyBotConfig;
|
use crate::configs::GeoffreyBotConfig;
|
||||||
|
@ -22,12 +23,22 @@ use serenity::{
|
||||||
};
|
};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
use geoffrey_models::logging::LogLevel;
|
||||||
|
use crate::logging::init_logging;
|
||||||
|
|
||||||
#[derive(Debug, StructOpt, Clone)]
|
#[derive(Debug, StructOpt, Clone)]
|
||||||
#[structopt(name = "GeoffreyBot", about = "Geoffrey Discord Bot")]
|
#[structopt(name = "GeoffreyBot", about = "Geoffrey Discord Bot")]
|
||||||
struct Args {
|
struct Args {
|
||||||
#[structopt(env = "GEOFFREY_BOT_CONFIG", parse(from_os_str))]
|
#[structopt(env = "GEOFFREY_BOT_CONFIG", parse(from_os_str))]
|
||||||
config: PathBuf,
|
config: PathBuf,
|
||||||
|
#[structopt(
|
||||||
|
short,
|
||||||
|
long,
|
||||||
|
env = "GEOFFREY_LOG_LEVEL",
|
||||||
|
parse(from_str),
|
||||||
|
default_value = "Info"
|
||||||
|
)]
|
||||||
|
log_level: LogLevel,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct HttpClient;
|
struct HttpClient;
|
||||||
|
@ -41,13 +52,13 @@ struct Handler;
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl EventHandler for Handler {
|
impl EventHandler for Handler {
|
||||||
async fn ready(&self, ctx: Context, ready: Ready) {
|
async fn ready(&self, ctx: Context, ready: Ready) {
|
||||||
println!("{} is connected!", ready.user.name);
|
log::info!("{} is connected!", ready.user.name);
|
||||||
let commands = create_commands(&ctx).await.unwrap();
|
let commands = create_commands(&ctx).await.unwrap();
|
||||||
|
|
||||||
println!("The following bot have been registered:");
|
log::debug!("The following bot have been registered:");
|
||||||
|
|
||||||
for command in commands {
|
for command in commands {
|
||||||
println!(
|
log::debug!(
|
||||||
"{}: {} - {:?}",
|
"{}: {} - {:?}",
|
||||||
command.name, command.description, command.options
|
command.name, command.description, command.options
|
||||||
);
|
);
|
||||||
|
@ -92,7 +103,7 @@ impl EventHandler for Handler {
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
} else if let Interaction::Ping(_) = interaction {
|
} else if let Interaction::Ping(_) = interaction {
|
||||||
println!("Ping recv'ed");
|
// do nothing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -100,21 +111,30 @@ impl EventHandler for Handler {
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let args: Args = Args::from_args();
|
let args: Args = Args::from_args();
|
||||||
|
init_logging(args.log_level).expect("Unable to init logging");
|
||||||
|
|
||||||
let cfg = match GeoffreyBotConfig::new(args.config.as_path()) {
|
let cfg = match GeoffreyBotConfig::new(args.config.as_path()) {
|
||||||
Ok(cfg) => cfg,
|
Ok(cfg) => cfg,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
println!("Error opening config: {}", e);
|
log::warn!("Error opening config: {}", e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut client = Client::builder(cfg.discord.token.clone())
|
let client = Client::builder(cfg.discord.token.clone())
|
||||||
.event_handler(Handler)
|
.event_handler(Handler)
|
||||||
.application_id(cfg.discord.app_id)
|
.application_id(cfg.discord.app_id)
|
||||||
.await
|
.await;
|
||||||
.expect("Error creating Geoffrey client");
|
|
||||||
|
|
||||||
|
let mut client = match client {
|
||||||
|
Ok(client) => client,
|
||||||
|
Err(e) => {
|
||||||
|
log::warn!("Unable to init serenity client: {}", e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Block for initializing global data
|
||||||
{
|
{
|
||||||
let mut data = client.data.write().await;
|
let mut data = client.data.write().await;
|
||||||
|
|
||||||
|
@ -124,7 +144,7 @@ async fn main() {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(why) = client.start().await {
|
if let Err(e) = client.start().await {
|
||||||
println!("Client error: {:?}", why);
|
log::warn!("Client error: {:?}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,3 +10,4 @@ edition = "2018"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
|
log = "0.4.14"
|
||||||
|
|
|
@ -4,6 +4,7 @@ use serde::Serialize;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
pub mod models;
|
pub mod models;
|
||||||
|
pub mod logging;
|
||||||
|
|
||||||
pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned + Debug {
|
pub trait GeoffreyDatabaseModel: Serialize + DeserializeOwned + Debug {
|
||||||
fn id(&self) -> Option<u64>;
|
fn id(&self) -> Option<u64>;
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
use log::LevelFilter;
|
||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
|
pub enum LogLevel {
|
||||||
|
None,
|
||||||
|
Warn,
|
||||||
|
Info,
|
||||||
|
Debug,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&str> for LogLevel {
|
||||||
|
#[allow(clippy::wildcard_in_or_patterns)]
|
||||||
|
fn from(s: &str) -> Self {
|
||||||
|
let s = s.to_lowercase();
|
||||||
|
match s.as_str() {
|
||||||
|
"warn" | "w" => LogLevel::Warn,
|
||||||
|
"info" | "i" => LogLevel::Info,
|
||||||
|
"debug" | "d" => LogLevel::Debug,
|
||||||
|
"none" | _ => LogLevel::None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LogLevel> for LevelFilter {
|
||||||
|
fn from(l: LogLevel) -> Self {
|
||||||
|
match l {
|
||||||
|
LogLevel::None => LevelFilter::Off,
|
||||||
|
LogLevel::Warn => LevelFilter::Warn,
|
||||||
|
LogLevel::Info => LevelFilter::Info,
|
||||||
|
LogLevel::Debug => LevelFilter::Debug,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue