use once_cell::sync::Lazy; use poise::serenity_prelude::{self as serenity, GatewayIntents}; mod command; pub struct Data {} // User data, which is stored and accessible in all command invocations type Context<'a> = poise::Context<'a, Data, anyhow::Error>; static ENV: Lazy = Lazy::new(|| { read_env() }); #[tokio::main] async fn main() { // Generate sick text like this: // http://www.patorjk.com/software/taag/#p=testall&f=Graffiti&t=hello%20world println!(r#" Invite this bot with: "#); println!("https://discord.com/api/oauth2/authorize?client_id={}&permissions={}&scope=bot", ENV.id, ENV.intents.bits(), ); print!("\n"); // Setup framework let framework = poise::Framework::builder() .options(poise::FrameworkOptions { commands: vec![ command::index_cmd(), command::scrape_all(), ], ..Default::default() }) .setup(|ctx, _ready, framework| { Box::pin(async move { poise::builtins::register_globally( ctx, &framework.options().commands ).await?; Ok(Data {}) }) }) .build(); // Start the Bot. let client = serenity::ClientBuilder::new(&ENV.token, ENV.intents) .framework(framework) .await; client.unwrap().start().await.unwrap(); } struct BotEnv { intents: GatewayIntents, token: String, id: String, } fn read_env() -> BotEnv { const DISCORD_INTENTS: &str = "DISCORD_INTENTS"; const DISCORD_TOKEN: &str = "DISCORD_TOKEN"; const DISCORD_ID: &str = "DISCORD_ID"; dotenv::dotenv().ok(); // ==================== ID =========================== let id: String = std::env::var(DISCORD_ID) .unwrap_or_else(|_| { println!(r#" WARN: Missing {DISCORD_ID} > This isn't really that problematic, just that the generated invite link won't work."#); String::from("") }); // ==================== Token ======================== let token: String = std::env::var(DISCORD_TOKEN) .unwrap_or_else(|_| panic!("ERROR: Missing {DISCORD_TOKEN}")); // ==================== Intents ====================== let intents_env: String = std::env::var(DISCORD_INTENTS) .unwrap_or_else(|msg| { println!("DEBUG: what is: {msg}"); println!("ERROR: Missing {DISCORD_INTENTS}"); "0".to_string() }); // ==================== Parse Intents ================= // parse into u64, then into GatewayIntents let intents_u64 = intents_env.parse::().unwrap_or(0u64); let intents_truncated: GatewayIntents = GatewayIntents::from_bits_truncate(intents_u64); if intents_truncated.bits() != intents_u64 { println!("WARN: Intents integer got truncated from {} to {}!", intents_u64, intents_truncated.bits()) }; BotEnv { intents: intents_truncated, token, id, } }