diff --git a/README.md b/README.md index 17e94cc..fb15fbd 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,18 @@ # echbot + A trash bot for Smite fun. + +## Environment + +You must set the following for the bot to run. + +```yml +environment: + - DISCORD_TOKEN=your_token_here + - GUILD_ID=your_guild_id_here +``` + +## Quotes + +A `quotes.txt` file must be present in the root directory for the ping command to function. The format is one quote per +line. diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..60e109e --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,3 @@ +// Group all commands for registration +pub(crate) mod slur; +pub(crate) mod team_up; diff --git a/src/commands/slur.rs b/src/commands/slur.rs new file mode 100644 index 0000000..ffcba29 --- /dev/null +++ b/src/commands/slur.rs @@ -0,0 +1,24 @@ +use crate::{Context, Error}; + +use rand::seq::IteratorRandom; +use std::{ + fs::File, + io::{BufRead, BufReader}, +}; + +/// Basically a ping command +#[poise::command(slash_command, prefix_command)] +pub(crate) async fn slur( + ctx: Context<'_>, +) -> Result<(), Error> { + let file = File::open("quotes.txt") + .unwrap_or_else(|_e| panic!("Quote file missing.")); // Open the quotes file + let file = BufReader::new(file); // Read the quotes file + let quotes = file.lines() + .map(|res| res.expect("Failed to read line.")); + let quote = quotes.choose(&mut rand::thread_rng()) + .expect("No lines in file."); // Pick a random quote + + ctx.say(quote).await?; + Ok(()) +} diff --git a/src/commands/team_up.rs b/src/commands/team_up.rs new file mode 100644 index 0000000..abdf18d --- /dev/null +++ b/src/commands/team_up.rs @@ -0,0 +1,17 @@ +use crate::{Context, Error}; +use crate::serenity; + +/// Split up users for custom joust matches +#[poise::command(slash_command, prefix_command)] +pub(crate) async fn team_up( + ctx: Context<'_>, + #[description = "Your voice channel"] channel: Option, +) -> Result<(), Error> { + let c = channel.as_ref().unwrap(); // Get channel info from object + let mut v = ctx.guild().unwrap().voice_states; // Get hashmap of users' voice states within the guild + v.retain(|_, s| s.channel_id == Some(c.id())); // Drop users not active in requested voice channel from hashmap + let res = format!("Channel {} has {} active users", c.id(), v.keys().len()); + + ctx.say(res).await?; + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index 752c6bd..8442cf4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,56 +1,33 @@ +mod commands; + use poise::serenity_prelude as serenity; -use rand::seq::IteratorRandom; -use std::{ - fs::File, - io::{BufRead, BufReader}, -}; struct Data {} type Error = Box; type Context<'a> = poise::Context<'a, Data, Error>; -/// Basically a ping command. -#[poise::command(slash_command, prefix_command)] -async fn slur( - ctx: Context<'_>, -) -> Result<(), Error> { - let file = File::open("quotes.txt").unwrap_or_else(|_e| panic!("Quote file missing.")); // Open the quotes file - let file = BufReader::new(file); // Read the quotes file - let quotes = file.lines().map(|res| res.expect("Failed to read line.")); - let quote = quotes.choose(&mut rand::thread_rng()).expect("No lines in file."); // Pick a random quote - - ctx.say(quote).await?; - Ok(()) -} - -/// Split up users for custom joust matches. -#[poise::command(slash_command, prefix_command)] -async fn team_up( - ctx: Context<'_>, - #[description = "Your voice channel"] channel: Option, -) -> Result<(), Error> { - let c = channel.as_ref().unwrap(); // Get channel info from object - let mut v = ctx.guild().unwrap().voice_states; // Get hashmap of users' voice states within the guild - v.retain(|_, s| s.channel_id == Some(c.id())); // Drop users not active in requested voice channel from hashmap - let res = format!("Channel {} has {} active users", c.id(), v.keys().len()); - - ctx.say(res).await?; - Ok(()) -} - #[tokio::main] async fn main() { let framework = poise::Framework::builder() .options(poise::FrameworkOptions { - commands: vec![slur(), team_up()], // IntelliJ doesn't like this, but it's fine. + commands: vec![ + commands::slur::slur(), + commands::team_up::team_up(), + ], // IntelliJ doesn't like this, but it's fine. ..Default::default() }) - .token(std::env::var("DISCORD_TOKEN").expect("missing DISCORD_TOKEN")) - .intents(serenity::GatewayIntents::non_privileged()) + .token(std::env::var("DISCORD_TOKEN") + .expect("Missing DISCORD_TOKEN")) + .intents(serenity::GatewayIntents::non_privileged()) // Set intents for Discord dev portal .setup(|ctx, _ready, framework| { Box::pin(async move { - poise::builtins::register_globally(ctx, &framework.options().commands).await?; + poise::builtins::register_in_guild( + ctx, + &framework.options().commands, + serenity::GuildId(std::env::var("GUILD_ID") + .expect("Missing GUILD_ID") // Get GID from env and parse + .parse::().unwrap())).await?; // Update slash commands in GID Ok(Data {}) }) });