161 lines
4.9 KiB
Rust
161 lines
4.9 KiB
Rust
#![deny(clippy::unwrap_used)]
|
|
#![deny(clippy::expect_used)]
|
|
#![deny(clippy::pedantic)]
|
|
|
|
mod arguments;
|
|
mod bot;
|
|
mod commands;
|
|
mod constants;
|
|
mod lua;
|
|
mod tasks;
|
|
|
|
use std::collections::HashMap;
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
use std::sync::{Arc, Condvar, OnceLock};
|
|
|
|
use bot::BotHandler;
|
|
use commands::{Command, CommandFnKind};
|
|
use metadata::LevelFilter;
|
|
use serenity::all::GatewayIntents;
|
|
use serenity::all::{Context, GuildId, ShardManager};
|
|
use serenity::model::channel::Message;
|
|
use serenity::Client;
|
|
use tracing::*;
|
|
|
|
// pub const CAT_DEV: &'static str = "Dev";
|
|
pub const CAT_FUN: &'static str = "Fun";
|
|
pub const CAT_MOD: &'static str = "Moderation";
|
|
pub const CAT_GEN: &'static str = "General";
|
|
pub const CAT_INF: &'static str = "Info";
|
|
pub const CAT_HID: &'static str = "Hidden";
|
|
|
|
static SHARD_MANAGER: OnceLock<Arc<ShardManager>> = OnceLock::new();
|
|
// static SHARDS_READY: AtomicBool = AtomicBool::new(false);
|
|
static DO_SHUTDOWN: (AtomicBool, Condvar) = (AtomicBool::new(false), Condvar::new()); // atombool and condvar combo to ensure maximum coverage when the bot needs to power off
|
|
|
|
#[tokio::main]
|
|
async fn main() {
|
|
tracing::subscriber::set_global_default(
|
|
tracing_subscriber::fmt()
|
|
.with_max_level(LevelFilter::INFO)
|
|
.finish(),
|
|
)
|
|
.unwrap();
|
|
|
|
info!("Logging initialized.");
|
|
|
|
let mut commands = HashMap::default();
|
|
|
|
info!("Loading stock commands.");
|
|
insert_stock(&mut commands);
|
|
info!("Loading rust dynamic commands.");
|
|
insert_rust(&mut commands);
|
|
|
|
info!("Initializing Lua runtime.");
|
|
let mut lua = lua::initialize(); // may not need to be mutable, but its fine for now
|
|
|
|
info!("Loading lua commandlets.");
|
|
insert_lua(&mut commands, &mut lua);
|
|
|
|
warn!("ABORTING CONNECTING TO DISCORD, BYE BYE!");
|
|
return;
|
|
|
|
// // TODO load this at runtime so the key will not be stored in the binary?
|
|
// #[cfg(not(debug_assertions))]
|
|
// let token = {
|
|
// info!("Initializing bot with production token.");
|
|
// include_str!("bot_token.prod")
|
|
// };
|
|
// #[cfg(debug_assertions)]
|
|
// let token = {
|
|
// info!("Initializing bot with development token.");
|
|
// include_str!("bot_token.dev")
|
|
// };
|
|
|
|
// let intents = GatewayIntents::DIRECT_MESSAGES
|
|
// | GatewayIntents::DIRECT_MESSAGE_REACTIONS
|
|
// | GatewayIntents::GUILDS
|
|
// | GatewayIntents::GUILD_MODERATION
|
|
// // | GatewayIntents::GUILD_EMOJIS_AND_STICKERS
|
|
// | GatewayIntents::GUILD_MEMBERS
|
|
// | GatewayIntents::GUILD_MESSAGE_REACTIONS
|
|
// | GatewayIntents::GUILD_MESSAGES
|
|
// | GatewayIntents::MESSAGE_CONTENT;
|
|
|
|
// let mut client = match Client::builder(&token, intents)
|
|
// .event_handler(BotHandler { commands })
|
|
// .await
|
|
// {
|
|
// Ok(client) => client,
|
|
// Err(err) => panic!("Error starting client connection: `{err}`"),
|
|
// };
|
|
|
|
// SHARD_MANAGER.set(client.shard_manager.clone()).unwrap();
|
|
|
|
// if let Err(why) = client.start_shards(2).await {
|
|
// error!("Client error: {why:?}");
|
|
// }
|
|
|
|
// warn!("MAIN FUNCTION EXITING");
|
|
}
|
|
|
|
/// The last set of commands, these are used by the hoster of the engine.
|
|
pub fn insert_lua(_commands: &mut HashMap<String, Command>, _lua: &mut mlua::Lua) {
|
|
// commands.insert(
|
|
// "stop".to_owned(),
|
|
// Command::new("stop".to_owned())
|
|
// .alias("svs".to_owned())
|
|
// .category(CAT_HID.to_owned())
|
|
// .hidden(true)
|
|
// .dm_command(CommandFnKind::Rust(stop_command))
|
|
// .guild_command(CommandFnKind::Rust(stop_command))
|
|
// .pretty_name("Stop the bot".to_owned())
|
|
// .help("Stops the bot. Does nothing unless you are a developer.".to_owned()),
|
|
// );
|
|
}
|
|
|
|
/// Cannot use any command names of stock commands, but gets to pick before lua commands are loaded.
|
|
pub fn insert_rust(_commands: &mut HashMap<String, Command>) {
|
|
// commands.insert(
|
|
// "stop".to_owned(),
|
|
// Command::new("stop".to_owned())
|
|
// .alias("svs".to_owned())
|
|
// .category(CAT_HID.to_owned())
|
|
// .hidden(true)
|
|
// .dm_command(CommandFnKind::Rust(stop_command))
|
|
// .guild_command(CommandFnKind::Rust(stop_command))
|
|
// .pretty_name("Stop the bot".to_owned())
|
|
// .help("Stops the bot. Does nothing unless you are a developer.".to_owned()),
|
|
// );
|
|
}
|
|
|
|
/// Will never fail, gets first pick of command names and properties. It is up to the maintainer to make damn sure this works.
|
|
pub fn insert_stock(commands: &mut HashMap<String, Command>) {
|
|
commands.insert(
|
|
"stop".to_owned(),
|
|
Command::new("stop".to_owned())
|
|
.alias("svs".to_owned())
|
|
.category(CAT_HID.to_owned())
|
|
.hidden(true)
|
|
.dm_command(CommandFnKind::Rust(stop_command))
|
|
.guild_command(CommandFnKind::Rust(stop_command))
|
|
.pretty_name("Stop the bot".to_owned())
|
|
.help("Stops the bot. Does nothing unless you are a developer.".to_owned()),
|
|
);
|
|
}
|
|
|
|
fn stop_command(_: Context, msg: Message, _: Option<GuildId>) {
|
|
// hardcode my id for now
|
|
if msg.author.id != 380045419381784576 {
|
|
return;
|
|
}
|
|
DO_SHUTDOWN.0.store(true, Ordering::SeqCst);
|
|
DO_SHUTDOWN.1.notify_all();
|
|
|
|
let handle = tokio::runtime::Handle::current();
|
|
let _eg = handle.enter();
|
|
|
|
handle.spawn(async {
|
|
SHARD_MANAGER.get().unwrap().shutdown_all().await;
|
|
});
|
|
}
|