diff --git a/src/main.rs b/src/main.rs index d5d3545..1401bc0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,11 +1,13 @@ -use std::env; +#![feature(async_closure)] -use poise::serenity_prelude as serenity; +use std::env; +use poise::{serenity_prelude::{self as serenity, Colour}, CreateReply}; struct Data {} type Error = Box; type Context<'a> = poise::Context<'a, Data, Error>; +/// Display the bot's latency to Discord's REST and Gateway APIs #[poise::command(slash_command)] async fn ping(ctx: Context<'_>) -> Result<(), Error> { use std::time::Instant; @@ -20,16 +22,83 @@ async fn ping(ctx: Context<'_>) -> Result<(), Error> { Ok(()) } +fn get_dox_output(ctx: &mut Context<'_>, user: &serenity::User, member: Option<&serenity::Member>, show_permissions: bool) -> String { + if user.bot { + return "This user is a bot.".into(); + } + + let mut output = String::new(); + + output.push_str(&format!("User ID: {}\n", user.id)); + + if let Some(locale) = &user.locale { + output.push_str(&format!("Locale: {locale}\n")); + } + + if let Some(verified) = &user.verified { + output.push_str(&format!("Verified: {verified}\n")); + } + + output.push_str(&format!("Account Created: {}\n", user.created_at())); + + if let Some(Some(join_date)) = member.as_ref().map(|m| m.joined_at) { + output.push_str(&format!("Joined this Server at: {join_date}\n")); + } + + if let Some(Some(premium_since)) = member.as_ref().map(|m| m.premium_since) { + output.push_str(&format!("Boosting this Server: Yes\nBoosting since: {premium_since}\n")); + } + + if show_permissions { + if let Some(member) = member { + if let Ok(permissions) = member.permissions(ctx) { + output.push_str(&format!("Permissions: {}\n", permissions.get_permission_names().join(", "))) + } + } + } + + output +} + +/// Display information about a given user +#[poise::command(slash_command)] +async fn dox( + mut ctx: Context<'_>, + #[description = "The user to display information of"] + user: serenity::User, + #[rename = "permissions"] + #[description = "Rather or not to show the user's permissions"] + show_permissions: Option) -> Result<(), Error> { + let user = ctx.http().get_user(user.id).await?; + let member = if let Some(guild) = ctx.guild_id() { + guild.member(ctx.http(), user.id).await.ok() + } else { + None + }; + + let embed = serenity::CreateEmbed::default() + .title(format!("Information about {}", user.name)) + .description(get_dox_output(&mut ctx, &user, member.as_ref(), show_permissions.unwrap_or(false))) + .colour(member.map(|m| m.colour(ctx.cache())) + .unwrap_or(None) + .unwrap_or(user.accent_colour.unwrap_or(Colour::from_rgb(255, 255, 255)))) + .image(user.face()); + + ctx.send(CreateReply::default().embed(embed)).await?; + + Ok(()) +} + #[tokio::main] async fn main() -> Result<(), Error> { dotenv::dotenv().ok(); let token = env::var("DISCORD_BOT_TOKEN")?; - let intents = serenity::GatewayIntents::non_privileged(); + let intents = serenity::GatewayIntents::all(); let framework = poise::Framework::builder() .options(poise::FrameworkOptions { - commands: vec![ping()], + commands: vec![ping(), dox()], ..Default::default() }) .setup(|ctx, _ready, framework| {