143 lines
5.2 KiB
Rust
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.");
|
|
}
|