From ec7315ebfdf56ea20c2a04bd642a36f8e7f18d94 Mon Sep 17 00:00:00 2001 From: ByteDice Date: Sat, 1 Mar 2025 01:48:00 +0100 Subject: [PATCH] command permissions & better styling --- README.md | 6 ++++- src/bk_week_cmds.rs | 57 ++++++++++++++++++++++++--------------------- src/cmds.rs | 41 +++++++++++++++++++++++--------- 3 files changed, 66 insertions(+), 38 deletions(-) diff --git a/README.md b/README.md index 650c4b7..c003b8d 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ An automation tool for Byte Dice. It's both a Discord and Reddit bot in one prog **You can learn more about copyright by reading the full [license](/LICENSE.txt).** ## How to run -### Dependecies: +### Dependencies: This program uses Rust (v1.82.0) and Python (v3.11.4), you can likely use other versions if they are compatible. This program also uses these Python modules: * asyncio @@ -40,6 +40,10 @@ You can install Python modules by running `$ pip install {module}` or `$ python | `ASSISTANT_R_PASS` | The password for the Reddit bot/account. | | `ASSISTANT_OWNERS` | A list of user ids that "own" the bot. Separate each owner with a comma and NO spaces. | +### Required permissions: +* Send Messages +* and... nothing else. + ### How to run: * Download the code (and extract if needed). * Open a terminal and CD to the downloaded folder. diff --git a/src/bk_week_cmds.rs b/src/bk_week_cmds.rs index b8173cc..e5dac22 100644 --- a/src/bk_week_cmds.rs +++ b/src/bk_week_cmds.rs @@ -42,7 +42,8 @@ async fn not_bk_mod_msg(ctx: Context<'_>) { #[poise::command( slash_command, - prefix_command + prefix_command, + required_bot_permissions = "SEND_MESSAGES" )] /// Shows helpful information on how to use the bk_week section of the bot. pub async fn bk_week_help( @@ -73,9 +74,10 @@ pub async fn bk_week_help( #[poise::command( slash_command, - prefix_command + prefix_command, + required_bot_permissions = "SEND_MESSAGES" )] -/// Retrieves the data of a single post just for you. The data has to be within the database to work. +/// Fetches the data of a single post, just for you. The data has to be within the database to work. pub async fn bk_week_get( ctx: Context<'_>, #[description = "The post URL."] url: String @@ -105,7 +107,7 @@ async fn get_post_from_data(ctx: Context<'_>, reddit_data: &Value, url: &str) -> if let Some(bk_week) = reddit_data.get(BK_WEEK) { if let Some(post) = bk_week.get(url) { if post.get("removed").is_some() { - send_post_removed_message(ctx, url, post.get("removed_by").unwrap().as_str().unwrap()).await; + send_post_removed_message(ctx, url, post).await; return Ok(None); } return Ok(Some(post.clone())); @@ -116,7 +118,7 @@ async fn get_post_from_data(ctx: Context<'_>, reddit_data: &Value, url: &str) -> } else { send_data_corrupted_message(ctx, url).await; - rs_println!("{}", serde_json::to_string_pretty(reddit_data).unwrap()); + rs_println!("{}", serde_json::to_string_pretty(reddit_data)?); } return Ok(None); } @@ -142,15 +144,10 @@ async fn send_post_not_found_message(ctx: Context<'_>, url: &str) { } -async fn send_post_removed_message(ctx: Context<'_>, url: &str, rm_by: &str) { - send_msg( +async fn send_post_removed_message(ctx: Context<'_>, url: &str, post: &Value) { + send_embed( ctx, - format!( - r#"Post URL \"<{}>\" is removed: Post is removed from the data! (Removed by: `{}`) - Hint: Run the command `/bk_week_add [URL]` in a Discord channel or `u/ByteDiceAssistant bk_week_add` in a Reddit post."#, - url, rm_by - ).trim().to_string(), - true, + embed_post_removed(post, url, true), true ).await; } @@ -174,7 +171,8 @@ async fn send_data_corrupted_message(ctx: Context<'_>, url: &str) { #[poise::command( slash_command, - prefix_command + prefix_command, + required_bot_permissions = "SEND_MESSAGES" )] /// Fetches a post from Reddit and adds it to the database. pub async fn bk_week_add( @@ -245,7 +243,8 @@ async fn send_updated_msg(ctx: Context<'_>, url: &str) { #[poise::command( slash_command, - prefix_command + prefix_command, + required_bot_permissions = "SEND_MESSAGES" )] /// Removes a post from the database. It will show who last removed it. pub async fn bk_week_remove( @@ -265,7 +264,7 @@ pub async fn bk_week_remove( if r["value"].as_bool().unwrap() { send_msg( ctx, - format!("Successfully flagged URL \"{}\" as `\"removed\": true` and `\"removed_by\": \"{}\"`", url, auth), + "Successfully flagged the post as removed!".to_string(), true, true ).await; @@ -282,7 +281,8 @@ pub async fn bk_week_remove( #[poise::command( slash_command, - prefix_command + prefix_command, + required_bot_permissions = "SEND_MESSAGES" )] /// Approves a post in the database. Approving posts tells the bot that it's original. pub async fn bk_week_approve( @@ -308,17 +308,17 @@ pub async fn bk_week_approve( async fn approve_cmd(ctx: Context<'_>, url: &str, reddit_data: &Value, approve: bool) { if let Some(post) = reddit_data.get(BK_WEEK).unwrap().get(&url) { if post.get("removed").is_some() { - send_post_removed_message(ctx, &url, post.get("removed_by").unwrap().as_str().unwrap()).await; + send_post_removed_message(ctx, &url, post).await; return; } let r = websocket::send_cmd_json("set_approve_post", Some(json!([approve, &url]))).await.unwrap(); if r.get("value").is_some() { if approve { - send_msg(ctx, format!("Successfully flagged URL \"<{}>\" as `approved:by_human`!", &url), true, true).await; + send_msg(ctx, "Successfully flagged the post as approved (by a human)!".to_string(), true, true).await; } else { - send_msg(ctx, format!("Successfully removed flag `approved:by_human` from URL \"<{}>\"!", &url), true, true).await; + send_msg(ctx, "Successfully removed the \"approved (by a human)\" flag from the post!".to_string(), true, true).await; } } else { @@ -337,7 +337,8 @@ async fn approve_cmd(ctx: Context<'_>, url: &str, reddit_data: &Value, approve: slash_command, prefix_command, default_member_permissions = "ADMINISTRATOR", - guild_only + guild_only, + required_bot_permissions = "SEND_MESSAGES" )] /// Sets the channel where the bot will dump all log info. It's recommended to only run this once. pub async fn bk_admin_bind( @@ -369,7 +370,8 @@ async fn send_server_not_in_data_msg(ctx: Context<'_>) { slash_command, prefix_command, guild_only, - guild_cooldown = 120 + guild_cooldown = 120, + required_bot_permissions = "SEND_MESSAGES" )] /// Updates all logs pub async fn bk_week_update( @@ -658,7 +660,8 @@ async fn remove_dupes(http: &Http, c_id: ChannelId, msgs_json: &Value) { #[poise::command( slash_command, - prefix_command + prefix_command, + required_bot_permissions = "SEND_MESSAGES" )] /// Adds/removes a vote from a post. These votes are not tied to Reddit upvotes. pub async fn bk_week_vote( @@ -678,7 +681,7 @@ pub async fn bk_week_vote( return Ok(()); } if post_data[&url].get("removed").is_some() { - send_post_removed_message(ctx, &url, post_data[&url]["removed_by"].as_str().unwrap()).await; + send_post_removed_message(ctx, &url, &post_data[&url]).await; return Ok(()); } @@ -721,7 +724,8 @@ pub async fn bk_week_vote( #[poise::command( slash_command, - prefix_command + prefix_command, + required_bot_permissions = "SEND_MESSAGES" )] /// Gets the top N (up to 10) posts within a certain category, such as upvotes. (Sorted descending.) pub async fn bk_week_top( @@ -790,7 +794,8 @@ fn smallest_n<'a>(map: &'a HashMap<&'a str, i32>, n: usize) -> Vec<(&'a str, i32 #[poise::command( slash_command, prefix_command, - owners_only + owners_only, + required_bot_permissions = "SEND_MESSAGES" )] /// Changes the subreddit(s) the bot patrols in. pub async fn bk_cfg_sr( diff --git a/src/cmds.rs b/src/cmds.rs index 1961117..b8a7453 100644 --- a/src/cmds.rs +++ b/src/cmds.rs @@ -10,7 +10,11 @@ use rand::{seq::IteratorRandom, Rng}; use regex::Regex; -#[poise::command(slash_command, prefix_command)] +#[poise::command( + slash_command, + prefix_command, + required_bot_permissions = "SEND_MESSAGES" +)] /// Check if you have connection to the bot. pub async fn ping( ctx: Context<'_>, @@ -26,8 +30,8 @@ pub async fn ping( #[poise::command( slash_command, prefix_command, - default_member_permissions = "ADMINISTRATOR", - owners_only + owners_only, + required_bot_permissions = "SEND_MESSAGES" )] /// Stops the bot... if you're mighty enough! pub async fn stop( @@ -61,8 +65,8 @@ pub async fn stop( #[poise::command( slash_command, prefix_command, - default_member_permissions = "ADMINISTRATOR", - owners_only + owners_only, + required_bot_permissions = "SEND_MESSAGES" )] /// Creates an embed. pub async fn embed( @@ -109,8 +113,8 @@ pub async fn embed( #[poise::command( slash_command, prefix_command, - default_member_permissions = "ADMINISTRATOR", - owners_only + owners_only, + required_bot_permissions = "SEND_MESSAGES" )] /// Sends a message. pub async fn send( @@ -125,7 +129,12 @@ pub async fn send( -#[poise::command(slash_command, prefix_command, rename = "8_ball")] +#[poise::command( + slash_command, + prefix_command, + rename = "8_ball", + required_bot_permissions = "SEND_MESSAGES" +)] /// Magic 8-ball. Ask a question, get an answer. pub async fn eight_ball( ctx: Context<'_>, @@ -147,7 +156,11 @@ pub async fn eight_ball( } -#[poise::command(slash_command, prefix_command)] +#[poise::command( + slash_command, + prefix_command, + required_bot_permissions = "SEND_MESSAGES" +)] /// Convert a long reddit URL to a short one. The bot ONLY uses shortURLs when asking for one. pub async fn re_shorturl( ctx: Context<'_>, @@ -180,7 +193,13 @@ pub fn to_shorturl(url: &str) -> Result { } -#[poise::command(slash_command, prefix_command, default_member_permissions = "ADMINISTRATOR", guild_only)] +#[poise::command( + slash_command, + prefix_command, + default_member_permissions = "ADMINISTRATOR", + guild_only, + required_bot_permissions = "SEND_MESSAGES" +)] /// Add your server to my database so I can sell it! (/s), I only store some minimal data the bot needs. pub async fn add_server( ctx: Context<'_> @@ -192,7 +211,7 @@ pub async fn add_server( send_msg(ctx, "Added your server to my data! Thanks for letting me steal it! (/s)".to_string(), true, true).await; } else { - send_msg(ctx, "Oopsies `(。>\\\\<)`. It looks like my data i-is \\**sob*\\*... c-cor-corrupted!".to_string(), true, true).await; + send_msg(ctx, "Oopsies `(。>\\\\<)`. It looks like my data i-is \\**sob*\\*... c-corrupted!".to_string(), true, true).await; } return Ok(());