use dotenv::dotenv; use poise::serenity_prelude as serenity; use std::{collections::HashMap, sync::Mutex}; use supabase::prelude::Client; mod commands; mod events; #[derive(Debug)] pub struct Data { pub state: AppState, } // Types used by all command functions type Error = Box; type Context<'a> = poise::Context<'a, Data, Error>; type ApplicationContext<'a> = poise::ApplicationContext<'a, Data, Error>; #[derive(Debug)] pub struct AppState { pub supabase: Client, pub student_cache: Mutex>, } impl AppState { pub async fn new() -> supabase::Result { dotenv().ok(); let supabase_url = std::env::var("SUPABASE_URL").expect("missing SUPABASE_URL"); let supabase_key = std::env::var("SUPABASE_KEY").expect("missing SUPABASE_KEY"); let supabase_user_email = std::env::var("SUPABASE_USER_EMAIL").expect("missing SUPABASE_USER_EMAIL"); let supabase_user_password = std::env::var("SUPABASE_USER_PASSWORD").expect("missing SUPABASE_USER_PASSWORD"); let client = Client::new(&supabase_url, &supabase_key)?; let auth_response = client .auth() .sign_in_with_email_and_password(&supabase_user_email, &supabase_user_password) .await?; if auth_response.user.is_none() { println!("User not found"); } else { println!( "User signed in: {}", auth_response .user .expect("User not found") .email .expect("Email not found") ); } Ok(Self { supabase: client, student_cache: Mutex::new(HashMap::new()), }) } } async fn event_handler( ctx: &serenity::Context, event: &serenity::FullEvent, _framework: poise::FrameworkContext<'_, Data, Error>, data: &Data, ) -> Result<(), Error> { match event { serenity::FullEvent::Ready { data_about_bot, .. } => { events::ready::on_ready(ctx, data_about_bot).await?; } serenity::FullEvent::InteractionCreate { interaction } => { events::interaction_create::on_interaction_create(ctx, interaction, &data).await?; } serenity::FullEvent::Message { new_message } => { events::message::on_message(ctx, new_message).await?; } _ => {} } Ok(()) } #[tokio::main] async fn main() { dotenv().ok(); // load env let app_state = AppState::new() .await .expect("Failed to initialize AppState"); // -- discord bot start -- let token = std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN"); let intents = serenity::GatewayIntents::non_privileged() | serenity::GatewayIntents::MESSAGE_CONTENT; let framework = poise::Framework::builder() .options(poise::FrameworkOptions { commands: vec![ commands::info::help(), commands::info::ping(), commands::info::userinfo(), commands::info::serverinfo(), commands::info::botinfo(), commands::weather::weather(), commands::verification::verify(), commands::mods_only::embed(), commands::member_info::member_info(), ], event_handler: |ctx, event, framework, data| { Box::pin(event_handler(ctx, event, framework, data)) }, ..Default::default() }) .setup(|ctx, _ready, framework| { Box::pin(async move { poise::builtins::register_globally(ctx, &framework.options().commands).await?; Ok(Data { state: app_state }) }) }) .build(); let client = serenity::ClientBuilder::new(token, intents) .framework(framework) .await; client .expect("Client failed to start") .start() .await .expect("Client failed to start"); // -- discord bot end -- }