2021-11-12 12:05:26 +00:00
#[ macro_use ] extern crate log ;
2021-11-12 13:56:05 +00:00
#[ macro_use ] extern crate serde ;
2021-11-12 12:05:26 +00:00
use std ::env ;
use std ::ops ::Deref ;
use std ::path ::PathBuf ;
use std ::sync ::Arc ;
2023-08-23 17:37:42 +00:00
2021-11-12 12:05:26 +00:00
use clap ::ArgMatches ;
2023-08-23 17:37:42 +00:00
use diesel ::r2d2 ::ConnectionManager ;
use diesel ::sqlite ::Sqlite ;
2021-11-12 12:05:26 +00:00
use diesel ::SqliteConnection ;
2023-08-23 17:37:42 +00:00
use diesel_migrations ::{ embed_migrations , EmbeddedMigrations , MigrationHarness } ;
use poise ::framework ::FrameworkBuilder ;
use poise ::serenity_prelude ::* ;
2022-07-17 23:25:59 +00:00
2023-08-23 17:37:42 +00:00
use crate ::config ::ManifoldConfig ;
use crate ::error ::{ ManifoldError , ManifoldResult } ;
use crate ::events ::Handler ;
use crate ::models ::user ::{ ManifoldUserInfo , UserInfo } ;
2021-11-12 12:05:26 +00:00
use crate ::responses ::Responses ;
pub mod config ;
pub mod error ;
pub mod events ;
2023-08-23 17:37:42 +00:00
pub mod responses ;
pub mod commands ;
pub mod models ;
pub mod schema ;
pub const MIGRATIONS : EmbeddedMigrations = embed_migrations! ( " migrations " ) ;
2021-11-12 13:23:14 +00:00
// Retrieve build info from output file
pub mod built_info {
include! ( concat! ( env! ( " OUT_DIR " ) , " /built.rs " ) ) ;
}
2023-08-23 17:37:42 +00:00
pub type ManifoldDatabasePool = r2d2 ::Pool < ConnectionManager < SqliteConnection > > ;
2021-11-12 12:05:26 +00:00
pub struct Db {
2021-11-12 22:28:51 +00:00
pub pool : ManifoldDatabasePool ,
2021-11-12 12:05:26 +00:00
}
impl Deref for Db {
2021-11-12 22:22:20 +00:00
type Target = ManifoldDatabasePool ;
2021-11-12 12:05:26 +00:00
fn deref ( & self ) -> & Self ::Target { & self . pool }
}
2021-11-12 22:22:20 +00:00
pub struct ManifoldDatabase ;
2021-11-12 12:05:26 +00:00
2023-08-23 17:37:42 +00:00
pub struct ManifoldData ( pub Arc < ManifoldDataInner > ) ;
impl Deref for ManifoldData {
type Target = ManifoldDataInner ;
2021-11-12 12:05:26 +00:00
2023-08-23 17:37:42 +00:00
fn deref ( & self ) -> & Self ::Target {
& self . 0
}
2021-11-12 12:05:26 +00:00
}
2023-08-23 17:37:42 +00:00
pub struct ManifoldDataInner {
bot_config : ManifoldConfig ,
database : Db ,
responses : Responses ,
user_info : Mutex < ManifoldUserInfo > ,
2021-11-12 12:05:26 +00:00
}
2023-08-23 17:37:42 +00:00
pub type ManifoldContext < ' a > = poise ::Context < ' a , ManifoldData , ManifoldError > ;
pub type ManifoldCommand = poise ::Command < ManifoldData , ManifoldError > ;
2021-11-12 12:15:59 +00:00
2023-08-23 17:37:42 +00:00
pub async fn prepare_client ( arguments : ArgMatches , intents : GatewayIntents , injected_commands : Vec < ManifoldCommand > ) -> ManifoldResult < FrameworkBuilder < ManifoldData , ManifoldError > > {
let bot_environment = arguments . get_one ( " environment " ) . unwrap ( ) ;
let config_file = format! ( " config/ {} " , arguments . get_one ::< String > ( " config-file " ) . unwrap ( ) ) ;
2021-11-12 12:05:26 +00:00
info! ( " Reading configuration... " ) ;
debug! ( " Configuration file path: {} " , & config_file ) ;
2023-08-23 17:37:42 +00:00
let config = ManifoldConfig ::load_config ( & config_file , bot_environment ) . expect ( & * format! ( " Could not read configuration file {} " , & config_file ) ) ;
2021-11-12 12:05:26 +00:00
2022-07-17 23:25:59 +00:00
let prefix = config . get_value ( & " BotPrefix " . to_string ( ) ) . expect ( " Could not read bot_prefix from config. " ) ;
2021-11-12 12:05:26 +00:00
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 ( ) ;
2022-07-17 23:25:59 +00:00
responses . reload ( & PathBuf ::from ( config . get_value ( & " ResponsesFilePath " . to_string ( ) ) . unwrap_or ( " txt/responses.txt " . to_string ( ) ) ) ) . expect ( " Could not load responses file! " ) ;
2021-11-12 12:05:26 +00:00
let token = env ::var ( " DISCORD_TOKEN " ) . expect (
" Could not find an environment variable called DISCORD_TOKEN " ,
) ;
2023-08-23 17:37:42 +00:00
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 " ) ;
Ok ( ManifoldData ( Arc ::new ( ManifoldDataInner {
bot_config : config ,
database : db ,
responses ,
user_info : Mutex ::new ( user_info ) ,
} ) ) )
} )
} ) ;
Ok ( framework )
2021-11-12 12:05:26 +00:00
}
2023-08-23 17:37:42 +00:00
fn apply_migrations ( conn : & mut impl MigrationHarness < Sqlite > ) {
2021-11-12 12:05:26 +00:00
2023-08-23 17:37:42 +00:00
conn . run_pending_migrations ( MIGRATIONS )
. expect ( " An error occurred applying migrations. " ) ;
2021-11-12 12:05:26 +00:00
}