manifold/src/lib.rs

143 lines
5.2 KiB
Rust

#[macro_use] extern crate log;
#[macro_use] extern crate serde;
use std::env;
use std::ops::Deref;
use std::path::PathBuf;
use std::sync::Arc;
use clap::ArgMatches;
use diesel::r2d2::ConnectionManager;
use diesel::sqlite::Sqlite;
use diesel::SqliteConnection;
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
use poise::framework::FrameworkBuilder;
use poise::serenity_prelude::*;
use crate::config::ManifoldConfig;
use crate::error::{ManifoldError, ManifoldResult};
use crate::events::Handler;
use crate::models::user::{ManifoldUserInfo, UserInfo};
use crate::responses::Responses;
pub mod autocomplete_helpers;
pub mod config;
pub mod error;
pub mod events;
pub mod responses;
pub mod commands;
pub mod models;
pub mod schema;
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("migrations");
// Retrieve build info from output file
pub mod built_info {
include!(concat!(env!("OUT_DIR"), "/built.rs"));
}
pub type ManifoldDatabasePool = r2d2::Pool<ConnectionManager<SqliteConnection>>;
pub struct Db {
pub pool: ManifoldDatabasePool,
}
impl Deref for Db {
type Target = ManifoldDatabasePool;
fn deref(&self) -> &Self::Target { &self.pool }
}
pub struct ManifoldDatabase;
pub struct ManifoldData(pub Arc<ManifoldDataInner>);
impl Deref for ManifoldData {
type Target = ManifoldDataInner;
fn deref(&self) -> &Self::Target {
&self.0
}
}
pub struct ManifoldDataInner {
bot_config: ManifoldConfig,
database: Db,
responses: Responses,
user_info: Mutex<ManifoldUserInfo>,
version_string: String,
}
pub type ManifoldContext<'a> = poise::Context<'a, ManifoldData, ManifoldError>;
pub type ManifoldCommand = poise::Command<ManifoldData, ManifoldError>;
pub async fn prepare_client(arguments: ArgMatches, intents: GatewayIntents, injected_commands: Vec<ManifoldCommand>, caller_version_string: String) -> ManifoldResult<FrameworkBuilder<ManifoldData, ManifoldError>> {
let bot_environment = arguments.get_one("environment").unwrap();
let config_file = format!("config/{}", arguments.get_one::<String>("config-file").unwrap());
info!("Reading configuration...");
debug!("Configuration file path: {}", &config_file);
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()).expect("Could not read bot_prefix from config.");
let manager = ConnectionManager::<SqliteConnection>::new("manifold.db");
let pool = r2d2::Pool::builder()
.max_size(1)
.build(manager)
.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!");
let token = env::var("DISCORD_TOKEN").expect(
"Could not find an environment variable called DISCORD_TOKEN",
);
let framework = poise::Framework::builder()
.options(poise::FrameworkOptions {
event_handler: |ctx, e, fctx, _| Box::pin(async move {
Handler::listen(ctx, fctx, e).await
}),
pre_command: |ctx: ManifoldContext<'_>| Box::pin(async move {
info!("Received command {} from {}", ctx.command().name, ctx.author().name);
let config = &ctx.data().bot_config;
let log_channel = config.get_channel(&"Log".to_string()).unwrap();
let _ = log_channel.say(ctx, format!("Received command {} from {}", ctx.command().name, ctx.author().name)).await;
}),
commands: commands::collect_commands(injected_commands),
prefix_options: poise::PrefixFrameworkOptions {
prefix: Some(prefix),
..Default::default()
},
..Default::default()
})
.token(token)
.intents(intents)
.setup(|ctx, _ready, framework| {
Box::pin(async move {
poise::builtins::register_globally(ctx, &framework.options().commands).await?;
ctx.set_activity(Activity::watching("you")).await;
let db = Db { pool };
apply_migrations(&mut db.get()?);
let user_info = UserInfo::load(&db).expect("Could not load user info, rejecting");
let git_info: String = built_info::GIT_VERSION.unwrap_or("unknown").to_string();
Ok(ManifoldData(Arc::new(ManifoldDataInner {
bot_config: config,
database: db,
responses,
user_info: Mutex::new(user_info),
version_string: format!("{caller} (Manifold framework version {mfold_ver} built at {mfold_time} from revision {mfold_rev})", caller=caller_version_string, mfold_ver=built_info::PKG_VERSION, mfold_time=built_info::BUILT_TIME_UTC, mfold_rev=git_info),
})))
})
});
Ok(framework)
}
fn apply_migrations(conn: &mut impl MigrationHarness<Sqlite>) {
conn.run_pending_migrations(MIGRATIONS)
.expect("An error occurred applying migrations.");
}