diff --git a/.env.example b/.env.example index 87fde69..5d46e09 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,10 @@ DISCORD_TOKEN="" +SUPABASE_URL="" +SUPABASE_KEY="" + +# Optional +VERIFIED_ROLE_ID="" +GUILD_ID="" WEATHER_TOKEN="" # Weather API token from: https://www.weatherapi.com/ \ No newline at end of file diff --git a/src/commands/verification.rs b/src/commands/verification.rs index 94286fe..4954722 100644 --- a/src/commands/verification.rs +++ b/src/commands/verification.rs @@ -1,10 +1,10 @@ -use crate::{Data, Error}; +use crate::{ApplicationContext, Error}; use dotenv::dotenv; use poise::{CreateReply, Modal}; use serde::{Deserialize, Serialize}; -use serenity::all::{CreateEmbed, CreateEmbedFooter, GuildId, RoleId}; - -type ApplicationContext<'a> = poise::ApplicationContext<'a, Data, Error>; +use serenity::all::{ + CreateActionRow, CreateButton, CreateEmbed, CreateEmbedFooter, GuildId, RoleId, +}; #[derive(Deserialize, Serialize, Debug)] struct StudentRow { @@ -24,47 +24,48 @@ struct VerificationModal { student_id: String, } -// #[poise::command(slash_command, subcommands("embed", "myself"))] -// pub async fn verify(_: ApplicationContext<'_>) -> Result<(), Error> { -// Ok(()) -// } +#[poise::command(slash_command, subcommands("embed", "myself"))] +pub async fn verify(_: ApplicationContext<'_>) -> Result<(), Error> { + Ok(()) +} /// Verify your DSEC club membership to obtain role #[poise::command(slash_command)] -pub async fn verify(ctx: ApplicationContext<'_>) -> Result<(), Error> { +pub async fn myself(ctx: ApplicationContext<'_>) -> Result<(), Error> { verify_member(ctx).await?; Ok(()) } -// #[poise::command(slash_command)] -// pub async fn verify(ctx: ApplicationContext<'_>) -> Result<(), Error> { -// let reply: CreateReply = { -// let embed: CreateEmbed = CreateEmbed::new() -// .title("Verify your DSEC membership") -// .description("Click **Verify Here** and enter your **Full name** and **Student ID** (e.g., s123456789). Your responses are private."); +#[poise::command(slash_command)] +pub async fn embed(ctx: ApplicationContext<'_>) -> Result<(), Error> { + let reply: CreateReply = { + let embed: CreateEmbed = CreateEmbed::new() + .title("Verify your DSEC membership") + .description("Click **Verify Here** and enter your **Full name** and **Student ID** (e.g., s123456789). Your responses are private."); -// let button: CreateButton = CreateButton::new("verify").label("Verify Here"); + let button: CreateButton = CreateButton::new("verify").label("Verify Here"); -// let components = vec![CreateActionRow::Buttons(vec![button])]; + let components = vec![CreateActionRow::Buttons(vec![button])]; -// CreateReply::default() -// .ephemeral(false) -// .embed(embed) -// .components(components) -// }; + CreateReply::default() + .ephemeral(false) + .embed(embed) + .components(components) + }; -// ctx.send(reply).await?; + ctx.send(reply).await?; -// while let Some(_) = ComponentInteractionCollector::new(ctx.serenity_context()) -// .filter(move |mci| mci.data.custom_id == "verify") -// .await -// { -// verify_member(ctx).await?; -// } + // let mut stream = ComponentInteractionCollector::new(ctx.serenity_context()) + // .filter(move |mci| mci.data.custom_id == "verify") + // .stream(); -// Ok(()) -// } + // while let Some(_) = stream.next().await { + // verify_member(ctx).await?; + // } + + Ok(()) +} // flow: // 1. check correct discord server -> layer 1 diff --git a/src/events.rs b/src/events.rs new file mode 100644 index 0000000..95ec4e9 --- /dev/null +++ b/src/events.rs @@ -0,0 +1,2 @@ +pub mod ready; +pub mod interaction_create; \ No newline at end of file diff --git a/src/events/interaction_create.rs b/src/events/interaction_create.rs new file mode 100644 index 0000000..489a428 --- /dev/null +++ b/src/events/interaction_create.rs @@ -0,0 +1,26 @@ +use crate::Error; +use poise::serenity_prelude as serenity; + +#[derive(Debug, poise::Modal)] +#[allow(dead_code)] // fields only used for Debug print +struct MyModal { + first_input: String, + second_input: Option, +} + +pub async fn on_interaction_create( + _ctx: &serenity::Context, + interaction: &serenity::Interaction, +) -> Result<(), Error> { + let some_message_component = interaction.as_message_component(); + + if !some_message_component.is_none() { + let component = some_message_component.unwrap(); + + if component.data.custom_id == "verify" { + println!("Component data: {:?}", component); + } + } + + Ok(()) +} diff --git a/src/events/ready.rs b/src/events/ready.rs new file mode 100644 index 0000000..08abed4 --- /dev/null +++ b/src/events/ready.rs @@ -0,0 +1,10 @@ +use crate::Error; +use poise::serenity_prelude as serenity; + +pub async fn on_ready( + _ctx: &serenity::Context, + data_about_bot: &serenity::Ready, +) -> Result<(), Error> { + println!("Logged in as {}", data_about_bot.user.name); + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index de1200c..9a7f23c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,8 +4,9 @@ use std::{ collections::HashMap, sync::{Arc, Mutex}, }; -use supabase::prelude::*; +use supabase::Client; mod commands; +mod events; pub struct Data { pub state: AppState, @@ -14,6 +15,7 @@ pub struct Data { // 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(Clone)] pub struct AppState { @@ -22,7 +24,7 @@ pub struct AppState { } impl AppState { - pub fn new() -> Result { + pub 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"); @@ -35,6 +37,24 @@ impl AppState { } } +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).await?; + } + _ => {} + } + Ok(()) +} + #[tokio::main] async fn main() { dotenv().ok(); // load env @@ -57,19 +77,14 @@ async fn main() { commands::verification::verify(), commands::mods_only::embed(), ], - event_handler: |_ctx, _event, _framework, _data| { - Box::pin(async move { - // println!("Got an event in event handler: {:?}", event); - - Ok(()) - }) + event_handler: |ctx, event, framework, data| { + Box::pin(event_handler(ctx, event, framework, data)) }, ..Default::default() }) .setup(|ctx, _ready, framework| { Box::pin(async move { - println!("Logged in as {}", _ready.user.name); poise::builtins::register_globally(ctx, &framework.options().commands).await?; Ok(Data { state: app_state }) })