diff --git a/README.md b/README.md index a5cf63e..4694233 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # ByteDiceAssistant -An automation tool for Byte Dice. It's both a Discord and Reddit bot in one program. +An automation tool primarily made for myself (Byte Dice) but publicly available for anyone to use. It's both a Discord and Reddit bot in one program. > [!CAUTION] > This tool is not intended for public use outside of the official *Byte Dice Assistant* bots. Expect issues if you host this yourself.\ -> This tool is only designed to run on Windows (10 and 11) and XUbuntu and may not work on any other OS. +> This tool is only designed to run on Windows (10 and 11) and XUbuntu (24.04 and above) and may not work on any other OS. -# Open-source - Copyright +## Open-source - Copyright **ByteDiceAssistant © 2025 by Byte Dice is licensed under CC BY-NC-SA 4.0.**\ **You can learn more about copyright by reading the full [license](/LICENSE.txt).** @@ -42,7 +42,7 @@ You can install Python modules by running `$ pip install {module}` or `$ python | `ASSISTANT_BK_MODS` | (OPTIONAL) Same format as `ASSISTANT_OWNERS` but for people who are allowed to use the `/bk_week` commands. | ### Required permissions: -**These are automatically set if you use the [official invite link](https://discord.com/oauth2/authorize?client_id=1212127255795335208&permissions=84992&integration_type=0&scope=bot) or an invite link with the permissions integer set to `84992`.** +**These are automatically set if you use the [official invite link](https://discord.com/oauth2/authorize?client_id=1212127255795335208&permissions=84992&integration_type=0&scope=bot) or an invite link with the permissions integer set to `84992`.** (The permission integer is this part of the URL `&permissions=84992`) * Send Messages * Read Message History * View Channels @@ -62,7 +62,7 @@ You can install Python modules by running `$ pip install {module}` or `$ python * write `VARIABLE_NAME="value"` + a new line for every variable. * if nano: `ctrl + O` (and press enter) then `ctrl + X`. * if VIM: press `esc` then write `:wq` (and press enter). -* Restart the terminal if you added/changed the environment variables. -* Run `$ cd path/to/extracted/folder`. -* Run `$ cargo run`. You can view a list of options by running `$ cargo run -- --help` or `$ cargo run -- -h`. +* Restart the terminal if you added/changed any environment variables. +* Run `$ cd path/to/extracted/folder` to navigate to the downloaded files (replace `path/to/extracted/folder` with your actual path). +* Run `$ cargo run` to start the program. You can view a list of options by running `$ cargo run -- --help` or `$ cargo run -- -h`. * If you only want to run the Python code, you can either run `$ cargo run -- --py`, or `$ python ./src/python/main.py`. The second option is recommended for better error output. \ No newline at end of file diff --git a/TODO.md b/TODO.md index 6f458fe..c6daea6 100644 --- a/TODO.md +++ b/TODO.md @@ -1,39 +1,12 @@ ### High priority: - - [ ] Reddit bot that scrapes images with tag "Original Art" and posts them in Discord server - [ ] Rename commands from "bk_week_{name}" to "re_{name}" - - - - - - - - - [ ] Allow disabling bk_week - - [ ] Allow updating the data autonomously and via manual commands. - - - - - - - - - - - [ ] Automatically approve posts that don't get caught by reverse image search (ris) - - - - - - - + ### Medium priority: - - [ ] View single rule (/rule {rule_name}) - [ ] Postfix calculator - [ ] Postfix generator @@ -41,7 +14,6 @@ - [ ] BPS args -> JSON - [ ] Random tip (from ByteDice.net/data/loadingScreenTips.json) - [ ] A command that just sends my socials - ### Low priority: - [ ] Particle of the week diff --git a/data/cfg_default.json b/data/cfg_default.json index 5f92ab3..96f17ae 100644 --- a/data/cfg_default.json +++ b/data/cfg_default.json @@ -1,5 +1,5 @@ { - "bk_week": { + "reddit": { "subreddits": "bytedicetesting", "fetch_limit": 100 } diff --git a/data/dc_data_preset.json b/data/dc_data_preset.json index 47bc7fb..502a5b4 100644 --- a/data/dc_data_preset.json +++ b/data/dc_data_preset.json @@ -1,13 +1,8 @@ { "servers": { "SERVER ID": { - "bk_week_channel": "CHANNEL ID INT", - "bk_mod_role": "bk mod", - "bk_mods": [ - "USER ID 1", - "USER ID 2" - ], - "bk_week_disabled": false + "re_posts_channel": 0, + "re_disabled": false } } } \ No newline at end of file diff --git a/data/lang/en.json b/data/lang/en.json index c8e2c85..e62c139 100644 --- a/data/lang/en.json +++ b/data/lang/en.json @@ -4,6 +4,7 @@ "dc_msg_bound_channel": "Successfully bound channel ID `{0}` as the \"where all collected Reddit data gets dumped\" channel!", "dc_msg_cmd_404": "No command \"{0}\" found!\nHint: Try `/help` without any arguments or `/help `", "dc_msg_corrupted_data": "Oopsies `(。>\\\\<)`. It looks like my data i-is \\**sob*\\*... c-corrupted!\n[From Byte Dice]: I have no idea what I was thinking while writing this at 2am. I'm not removing it.", + "dc_msg_data_server_404": "This server is not in the data!\n Hint: Run the command `/add_server` inside of a Discord server (requires administrator permission).", "dc_msg_dm_python_err_socket": "Unknown internal Python error occurred: Websocket response error", "dc_msg_dm_python_err": "Unknown internal Python Error: {0}", "dc_msg_embed_default_embed_desc": "Default english embed description.", @@ -17,24 +18,24 @@ "dc_msg_owner_shutdown_failed_confirmation": "Failed to shut down: Invalid confirmation.", "dc_msg_re_already_voted": "Couldn't cast a vote: You have already voted on this post!", "dc_msg_re_also_approved": "Also approved it!", - "dc_msg_re_data_corrupted": "Post URL \"<{0}>\" not found: Post data is corrupted!\n Full details: Could not find key \"bk_weekly_art_posts\" in data file \"reddit_data.json\"", - "dc_msg_re_help_removed": "Reddit help file not found, someone likely deleted it.\n Hint: You can find the official help text at https://github.com/ByteDice/ByteDiceAssistant in `bk_week_help_re.md`.\n**CAUTION:** The official help file may contain incorrect information if you're not using the official bot by Byte Dice.", + "dc_msg_re_data_corrupted": "Post URL \"<{0}>\" not found: Post data is corrupted!\n Full details: Could not find key \"posts\" in data file \"re_data.json\"", + "dc_msg_re_help_removed": "Reddit help file not found, someone likely deleted it.\n Hint: You can find the official help text at https://github.com/ByteDice/ByteDiceAssistant in `re_help.md`.\n**CAUTION:** The official help file may contain incorrect information if you're not using the official bot by Byte Dice.", "dc_msg_re_permdeny_not_re_mod": "Permission denied: You are not a moderator of the subreddit(s) {0}", - "dc_msg_re_post_404": "Post URL \"<{0}>\" not found: Post doesn't exist in the data!\n Hint: Run the command `/re_addPost [URL]` in a Discord channel or `u/ByteDiceAssistant bk_week_add` in a Reddit post.", + "dc_msg_re_post_404": "Post URL \"<{0}>\" not found: Post doesn't exist in the data!\n Hint: Run the command `/re_addpost [URL]` in a Discord channel or `u/ByteDiceAssistant add_post` in a Reddit post.", "dc_msg_re_post_add_success": "Added post with URL \"<{0}>\"!", "dc_msg_re_post_approve_success": "Successfully approved the post!", "dc_msg_re_post_disapprove_success": "Successfully disapproved the post!", "dc_msg_re_post_remove_success": "Successfully removed post!", "dc_msg_re_post_unremove_success": "Successfully un-removed post with URL \"<{0}>\"!", "dc_msg_re_post_update_success": "Updated post with URL \"<{0}>\"!", - "dc_msg_re_vote_err": "Failed to vote/un-vote: Unknown internal error.", + "dc_msg_re_posts_channel_404": "Could not find `re_posts_channel` in data!\nHint: Run `/admin_re_bindchannel` in a (preferably read-only) channel (requires administrator permission).", + "dc_msg_re_vote_err": "Failed to [vote / un-vote]: Unknown internal error.", "dc_msg_re_vote_mod_success": "Successfully voted (as moderator vote)!", "dc_msg_re_vote_remove_havent": "Couldn't remove your vote: You haven't voted on this post yet!", "dc_msg_re_vote_remove_success": "Successfully removed vote!", "dc_msg_re_vote_success": "Successfully voted!", "dc_msg_reload_cfg_python_fail": "Failed to reload configs: Failed-type response from Python.", "dc_msg_reload_cfg_success": "Successfully reloaded the configs!\nNew configs:\n```\n{0}\n```", - "dc_msg_server_data_404": "This server is not in the data!\n Hint: Run the command `/add_server` inside of a Discord server (requires administrator permission).", "dc_msg_shorturl": "ShortURL: <{0}>", "log_lang_load_success": "Successfully loaded the english language file!" } \ No newline at end of file diff --git a/data/re_data_preset.json b/data/re_data_preset.json index 587fc1c..f5ec648 100644 --- a/data/re_data_preset.json +++ b/data/re_data_preset.json @@ -1,5 +1,5 @@ { - "bk_weekly_art_posts": { + "posts": { "EXAMPLE VALUE": { "post_data": { "title": "I JUST BOUGHT THE CONTINENT OF NORTH AMERICA FOR A DOLLAR!", diff --git a/src/data.rs b/src/data.rs index 1f8a81a..133243e 100644 --- a/src/data.rs +++ b/src/data.rs @@ -4,7 +4,7 @@ use std::path::Path; use serde_json::{self, Value, json}; use tokio::sync::Mutex; -use crate::{errln, rs_println, Data, Error, BK_WEEK, LANG}; +use crate::{errln, rs_println, Data, Error, CFG_DATA_RE, LANG}; use crate::websocket::send_cmd_json; @@ -16,6 +16,8 @@ static DATA_PATH_CFG: &str = "./data/cfg.json"; static PRESET_PATH_CFG: &str = "./data/cfg_default.json"; static DATA_PATH_LANG: &str = "./data/lang/"; +pub static DC_POSTS_CHANNEL_KEY: &str = "re_posts_channel"; + pub async fn read_dc_data(data: &Data, wipe: bool) { if !Path::new(DATA_PATH_DC).exists() || wipe { @@ -88,7 +90,7 @@ fn generate_re_data() { let preset_str = fs::read_to_string(PRESET_PATH_RE).unwrap(); let mut preset_json: Value = serde_json::from_str(&preset_str).unwrap(); - if let Some(bk_week) = preset_json[BK_WEEK].as_object_mut() { + if let Some(bk_week) = preset_json[CFG_DATA_RE].as_object_mut() { bk_week.remove("EXAMPLE VALUE"); bk_week.remove("EXAMPLE VALUE DELETED"); } @@ -149,7 +151,7 @@ pub async fn dc_add_server(data: &Data, server_id: u64) -> Result<(), ()> { let servers = dc_data["servers"].as_object_mut().unwrap(); if !servers.contains_key(&server_id.to_string()) { - servers.insert(server_id.to_string(), json!({ "bk_week_channel": 0 })); + servers.insert(server_id.to_string(), json!({ DC_POSTS_CHANNEL_KEY: 0 })); } return Ok(()); @@ -170,7 +172,7 @@ pub async fn dc_bind_bk(data: &Data, server_id: u64, channel_id: u64) -> Result< let server = servers[&server_id.to_string()].as_object_mut().unwrap(); - server.insert("bk_week_channel".to_string(), channel_id.into()); + server.insert(DC_POSTS_CHANNEL_KEY.to_string(), channel_id.into()); return Ok(()); } diff --git a/src/main.rs b/src/main.rs index 13a1315..09ba2d3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -59,7 +59,7 @@ struct Args { noping: bool, #[arg(long, help = "Makes the program not use the schedules.")] nosched: bool, - #[arg(long, default_value = "en", help = "Which language file to use (Do not include file extention)")] + #[arg(long, default_value = "en", help = "Which language file to use (Do not include file extensions)")] lang: String } @@ -79,7 +79,7 @@ struct Data { } -static BK_WEEK: &str = "bk_weekly_art_posts"; +static CFG_DATA_RE: &str = "posts"; pub static mut LANG: Option = None; @@ -100,19 +100,19 @@ async fn main() { .map(|s| s.parse::().expect("Failed to parse ASSISTANT_OWNERS. Invalid syntax.")) .collect(); - if args.test { println!("----- USING TEST BOT -----"); } - if args.dev { println!("----- DEV MODE ENABLED -----"); } + if args.test { println!("----- USING TEST BOT -----"); } + if args.dev { println!("----- DEV MODE ENABLED -----"); } if args.dev && args.wipe { println!("----- \"DON'T WORRY ABOUT IT\" MODE ENABLED -----"); } - if args.nosched { println!("----- NO SCHEDULES -----") } + if args.nosched { println!("----- NO SCHEDULES -----"); } if args.py && !args.rs { - println!("----- PYTHON ONLY MODE -----"); + println!("----- PYTHON ONLY MODE -----"); rs_println!("ARGS: {}", args_str); let _ = python::start(args).await; process::exit(0); } else if args.rs && ! args.py { - println!("----- RUST ONLY MODE -----"); + println!("----- RUST ONLY MODE -----"); rs_println!("ARGS: {}", args_str); start(args, own_vec_u64.clone()).await; process::exit(0); diff --git a/src/python/bot.py b/src/python/bot.py index ba57c7f..c622ce1 100644 --- a/src/python/bot.py +++ b/src/python/bot.py @@ -6,8 +6,8 @@ from macros import * import json -BK_WEEKLY: Final[str] = "bk_weekly_art_posts" -BK_WEEK: Final[str] = "bk_week" +RE_DATA_POSTS: Final[str] = "posts" +CFG_DATA_RE: Final[str] = "reddit" class Bot: @@ -22,7 +22,7 @@ class Bot: useragent: str =\ f"{username} by u/RandomPersonDotExe aka u/Byte_Dice"\ if r_id == "YmZjr4zLr2qtHdpQXtj0sBOOdJzrXQ"\ - else f"{username} (original program by u/RandomPersonDotExe aka u/Byte_Dice)" + else f"{username} (Original program by u/RandomPersonDotExe aka u/Byte_Dice)" if password is None: py_error("Environment variable \"ASSISTANT_R_PASS\" is null!") @@ -57,11 +57,11 @@ class Bot: async def update_cfg_str(self, new_cfg: str) -> bool: json_cfg = json.loads(new_cfg) - self.sr = await self.r.subreddit(json_cfg[BK_WEEK]["subreddits"]) - self.fetch_limit = json_cfg[BK_WEEK]["fetch_limit"] + self.sr = await self.r.subreddit(json_cfg[CFG_DATA_RE]["subreddits"]) + self.fetch_limit = json_cfg[CFG_DATA_RE]["fetch_limit"] return True async def update_cfg(self, new_cfg: dict) -> bool: - self.sr = await self.r.subreddit(new_cfg[BK_WEEK]["subreddits"]) - self.fetch_limit = new_cfg[BK_WEEK]["fetch_limit"] + self.sr = await self.r.subreddit(new_cfg[CFG_DATA_RE]["subreddits"]) + self.fetch_limit = new_cfg[CFG_DATA_RE]["fetch_limit"] return True \ No newline at end of file diff --git a/src/python/cmds.py b/src/python/cmds.py index 4e9b0f9..3f2e2f2 100644 --- a/src/python/cmds.py +++ b/src/python/cmds.py @@ -6,7 +6,7 @@ import data import posts -BOT_ACTION_POSTFIX = "\n\n^(I am not an AI, I am just a bot. This action was performed automatically by the way.)" +BOT_ACTION_POSTFIX = "^(I am not an AI, I am just a bot. This action was performed automatically by the way. You can report bugs and view my source code [here](https://github.com/ByteDice/ByteDiceAssistant)!)" async def make_cmd(cmd: str, bot: botPy.Bot) -> str: @@ -29,7 +29,7 @@ async def respond_to_mention(bot: botPy.Bot) -> bool: py_print(f"New mention: {truncated}") - if await is_cmd("bk_week_add", body, bot): + if await is_cmd("add_post", body, bot): await bk_week_add(mention, bot) else: @@ -57,17 +57,16 @@ async def bk_week_add(mention: models.Comment, bot: botPy.Bot): short_url = mention.submission.shortlink r = "" - bd = bot.data[botPy.BK_WEEKLY] - # TODO: ask if the messages should be changed + bd = bot.data[botPy.RE_DATA_POSTS] if short_url not in bd: posts.add_post_url(bot, short_url) r = "Successfully added this post to the data!" if short_url in bd and is_mod: if "removed" in bd[short_url]: - r = "(Mod action) Successfully un-removed this post from the data!" + r = "[MOD ACTION] Successfully un-removed this post from the data!" else: - r = "(Mod action) Successfully added this post to the data!" + r = "[MOD ACTION] Successfully added this post to the data!" post = await posts.from_url(bot, short_url) post_data = posts.get_post_details(post[1]) @@ -77,5 +76,5 @@ async def bk_week_add(mention: models.Comment, bot: botPy.Bot): r = "Could not add this post to the data. Luckily, it's already there, so there's nothing to worry about!" - await mention.reply(r + " Thank you for participating!" + BOT_ACTION_POSTFIX) + await mention.reply(r + " Thank you for participating!" + "\n\n" + BOT_ACTION_POSTFIX) await mention.mark_read() \ No newline at end of file diff --git a/src/python/data.py b/src/python/data.py index de6dfde..794b3c3 100644 --- a/src/python/data.py +++ b/src/python/data.py @@ -79,8 +79,8 @@ def read_data(bot: botPy.Bot) -> bool: with open(os.path.join(DATA_PATH, "re_data_preset.json", "r")) as f: data_preset_json = json.load(f) - data_preset_json[botPy.BK_WEEKLY].pop("EXAMPLE VALUE", None) - data_preset_json[botPy.BK_WEEKLY].pop("EXAMPLE VALUE DELETED", None) + data_preset_json[botPy.RE_DATA_POSTS].pop("EXAMPLE VALUE", None) + data_preset_json[botPy.RE_DATA_POSTS].pop("EXAMPLE VALUE DELETED", None) with open(r_path, "w") as f: json.dump(data_preset_json, f, indent = 2) @@ -126,7 +126,7 @@ async def read_cfg(bot: botPy.Bot) -> bool: def add_post_to_data(bot: botPy.Bot, new_data: PostData, bypass_conditions: bool = False) -> bool: if bypass_conditions: - bot.data[botPy.BK_WEEKLY][new_data.url] = new_data.to_json() + bot.data[botPy.RE_DATA_POSTS][new_data.url] = new_data.to_json() if bot.args["dev"]: py_print(f"Added post \"{new_data.url}\" (Conditions bypassed)") return True @@ -134,14 +134,14 @@ def add_post_to_data(bot: botPy.Bot, new_data: PostData, bypass_conditions: bool # not sure what this is for updated = False - if new_data.url not in bot.data[botPy.BK_WEEKLY] or updated: - bot.data[botPy.BK_WEEKLY][new_data.url] = new_data.to_json() + if new_data.url not in bot.data[botPy.RE_DATA_POSTS] or updated: + bot.data[botPy.RE_DATA_POSTS][new_data.url] = new_data.to_json() if bot.args["dev"]: py_print(f"Added post \"{new_data.url}\"") return True - if "removed" not in bot.data[botPy.BK_WEEKLY][new_data.url]: - updated = new_data.upvotes != bot.data[botPy.BK_WEEKLY][new_data.url]["post_data"] + if "removed" not in bot.data[botPy.RE_DATA_POSTS][new_data.url]: + updated = new_data.upvotes != bot.data[botPy.RE_DATA_POSTS][new_data.url]["post_data"] else: py_print(f"Failed to add post \"{new_data.url}\": Removed flag is True.") @@ -149,15 +149,15 @@ def add_post_to_data(bot: botPy.Bot, new_data: PostData, bypass_conditions: bool def set_approve_post(bot: botPy.Bot, approved: bool, url: str) -> bool: - if not hasattr(bot.data[botPy.BK_WEEKLY][url], "removed"): - bot.data[botPy.BK_WEEKLY][url]["approved"]["by_human"] = approved + if not hasattr(bot.data[botPy.RE_DATA_POSTS][url], "removed"): + bot.data[botPy.RE_DATA_POSTS][url]["approved"]["by_human"] = approved return True return False def remove_post(bot: botPy.Bot, url: str, removed_by: str = "UNKNOWN", reason: str = "None") -> bool: - weekly = bot.data[botPy.BK_WEEKLY] + weekly = bot.data[botPy.RE_DATA_POSTS] if url in weekly: weekly[url] = { @@ -173,7 +173,7 @@ def remove_post(bot: botPy.Bot, url: str, removed_by: str = "UNKNOWN", reason: s def remove_old_posts(bot: botPy.Bot, max_age: int) -> bool: now = int(time.time()) - weekly = bot.data[botPy.BK_WEEKLY] + weekly = bot.data[botPy.RE_DATA_POSTS] remove: list[str] = [] for url, post in weekly.items(): @@ -194,10 +194,10 @@ def set_vote_post( from_dc: bool = False, remove_vote: bool = False, ) -> bool: - if url not in bot.data[botPy.BK_WEEKLY]: + if url not in bot.data[botPy.RE_DATA_POSTS]: return False - votes = bot.data[botPy.BK_WEEKLY][url]["votes"] + votes = bot.data[botPy.RE_DATA_POSTS][url]["votes"] re_voters: set[str] = set(votes["voters_re"]) dc_voters: set[int] = set(votes["voters_dc"]) mod_voters: set[int] = set(votes["mod_voters"]) @@ -214,8 +214,8 @@ def set_vote_post( return False target_voters.add(user) - bot.data[botPy.BK_WEEKLY][url]["votes"]["voters_re"] = list(re_voters) - bot.data[botPy.BK_WEEKLY][url]["votes"]["voters_dc"] = list(dc_voters) - bot.data[botPy.BK_WEEKLY][url]["votes"]["mod_voters"] = list(mod_voters) + bot.data[botPy.RE_DATA_POSTS][url]["votes"]["voters_re"] = list(re_voters) + bot.data[botPy.RE_DATA_POSTS][url]["votes"]["voters_dc"] = list(dc_voters) + bot.data[botPy.RE_DATA_POSTS][url]["votes"]["mod_voters"] = list(mod_voters) return True diff --git a/src/re_cmds/add.rs b/src/re_cmds/add.rs index 7e24838..06e8813 100644 --- a/src/re_cmds/add.rs +++ b/src/re_cmds/add.rs @@ -2,8 +2,8 @@ use serde_json::json; use crate::data::get_mutex_data; use crate::messages::send_msg; -use crate::{data, websocket, Context, Error, BK_WEEK}; -use crate::re_cmds::generic_fns::{is_bk_mod, to_shorturl}; +use crate::{data, websocket, Context, Error, CFG_DATA_RE}; +use crate::re_cmds::generic_fns::{get_readable_subreddits, is_bk_mod, to_shorturl}; use crate::lang; #[poise::command( @@ -21,7 +21,8 @@ pub async fn cmd( ) -> Result<(), Error> { if !is_bk_mod(ctx.data().bk_mods.clone(), ctx.author().id.get()) { - send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod"), false, false).await; // TODO: add subreddit arg to lang + let sr = get_readable_subreddits(ctx).await?; + send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod", sr), false, false).await; return Ok(()); } @@ -31,7 +32,7 @@ pub async fn cmd( data::update_re_data(ctx.data()).await; let reddit_data = get_mutex_data(&ctx.data().reddit_data).await?; - if let Some(bk_week) = reddit_data.get(BK_WEEK) { + if let Some(bk_week) = reddit_data.get(CFG_DATA_RE) { let a = approve.unwrap_or(false); let r = websocket::send_cmd_json("add_post_url", Some(json!([&shorturl, a, true]))).await.unwrap(); diff --git a/src/re_cmds/approve.rs b/src/re_cmds/approve.rs index da3b8c2..115be82 100644 --- a/src/re_cmds/approve.rs +++ b/src/re_cmds/approve.rs @@ -1,6 +1,6 @@ use serde_json::{json, Value}; -use crate::{data::{self, get_mutex_data}, lang, messages::send_msg, re_cmds::generic_fns::is_bk_mod, websocket, Context, Error, BK_WEEK}; +use crate::{data::{self, get_mutex_data}, lang, messages::send_msg, re_cmds::generic_fns::{get_readable_subreddits, is_bk_mod}, websocket, Context, Error, CFG_DATA_RE}; use super::generic_fns::send_embed_for_removed; @@ -19,7 +19,8 @@ pub async fn cmd( ) -> Result<(), Error> { if !is_bk_mod(ctx.data().bk_mods.clone(), ctx.author().id.get()) { - send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod"), false, false).await; + let sr = get_readable_subreddits(ctx).await?; + send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod", sr), false, false).await; return Ok(()); } @@ -33,7 +34,7 @@ pub async fn cmd( 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 let Some(post) = reddit_data.get(CFG_DATA_RE).unwrap().get(url) { if post.get("removed").is_some() { send_embed_for_removed(ctx, url, post).await; return; diff --git a/src/re_cmds/generic_fns.rs b/src/re_cmds/generic_fns.rs index e5a6b2d..2f104d1 100644 --- a/src/re_cmds/generic_fns.rs +++ b/src/re_cmds/generic_fns.rs @@ -1,7 +1,7 @@ use regex::Regex; use serde_json::Value; -use crate::{messages::{make_post_embed, make_removed_embed, send_embed}, Context, Error}; +use crate::{data::get_mutex_data, messages::{make_post_embed, make_removed_embed, send_embed}, Context, Error}; pub fn is_bk_mod(mod_list: Vec, uid: u64) -> bool { return mod_list.contains(&uid); @@ -31,4 +31,14 @@ pub async fn send_embed_for_removed(ctx: Context<'_>, url: &str, post: &Value) { make_removed_embed(post, url, true), true ).await; +} + + +pub async fn get_readable_subreddits(ctx: Context<'_>) -> Result { + let d = get_mutex_data(&ctx.data().cfg).await?; + let sr = d["reddit"]["subreddits"].as_str().ok_or("Item of key \"subreddit\" is not a string type.\nTrace: get_readable_subreddits -> let sr = ...")?; + let split: Vec<&str> = sr.split("+").collect(); + let join = split.join(", r/"); + + return Ok(join); } \ No newline at end of file diff --git a/src/re_cmds/get.rs b/src/re_cmds/get.rs index 7e99817..5292461 100644 --- a/src/re_cmds/get.rs +++ b/src/re_cmds/get.rs @@ -1,6 +1,6 @@ use serde_json::Value; -use crate::{data::{self, get_mutex_data}, lang, messages::send_msg, re_cmds::generic_fns::send_embed_for_post, rs_println, Context, Error, BK_WEEK}; +use crate::{data::{self, get_mutex_data}, lang, messages::send_msg, re_cmds::generic_fns::send_embed_for_post, rs_println, Context, Error, CFG_DATA_RE}; use super::generic_fns::send_embed_for_removed; @@ -30,7 +30,7 @@ pub async fn cmd( async fn get_post_from_data(ctx: Context<'_>, reddit_data: &Value, url: &str) -> Result, Error> { - if let Some(bk_week) = reddit_data.get(BK_WEEK) { + if let Some(bk_week) = reddit_data.get(CFG_DATA_RE) { if let Some(post) = bk_week.get(url) { if post.get("removed").is_some() { send_embed_for_removed(ctx, url, post).await; diff --git a/src/re_cmds/remove.rs b/src/re_cmds/remove.rs index 7a60046..d08a785 100644 --- a/src/re_cmds/remove.rs +++ b/src/re_cmds/remove.rs @@ -1,6 +1,6 @@ use serde_json::json; -use crate::{lang, messages::send_msg, re_cmds::generic_fns::is_bk_mod, websocket::send_cmd_json, Context, Error}; +use crate::{lang, messages::send_msg, re_cmds::generic_fns::{get_readable_subreddits, is_bk_mod}, websocket::send_cmd_json, Context, Error}; #[poise::command( slash_command, @@ -17,7 +17,8 @@ pub async fn cmd( ) -> Result<(), Error> { if !is_bk_mod(ctx.data().bk_mods.clone(), ctx.author().id.get()) { - send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod"), false, false).await; + let sr = get_readable_subreddits(ctx).await?; + send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod", sr), false, false).await; return Ok(()); } diff --git a/src/re_cmds/top.rs b/src/re_cmds/top.rs index e723d11..5f4873e 100644 --- a/src/re_cmds/top.rs +++ b/src/re_cmds/top.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use crate::{data::get_mutex_data, re_cmds::generic_fns::send_embed_for_post, Context, Error, BK_WEEK}; +use crate::{data::get_mutex_data, re_cmds::generic_fns::send_embed_for_post, Context, Error, CFG_DATA_RE}; #[derive(poise::ChoiceParameter, PartialEq)] enum TopCategory { @@ -30,7 +30,7 @@ pub async fn cmd( ) -> Result<(), Error> { let mut all: HashMap<&str, i32> = HashMap::new(); - let posts = &get_mutex_data(&ctx.data().reddit_data).await?[BK_WEEK]; + let posts = &get_mutex_data(&ctx.data().reddit_data).await?[CFG_DATA_RE]; let posts_u = posts.as_object().unwrap(); for (url, dat) in posts_u { diff --git a/src/re_cmds/update.rs b/src/re_cmds/update.rs index 6197b6f..d522e76 100644 --- a/src/re_cmds/update.rs +++ b/src/re_cmds/update.rs @@ -3,7 +3,7 @@ use std::time::{SystemTime, UNIX_EPOCH}; use poise::{serenity_prelude::{ChannelId, EditMessage, GetMessages, Http, Message, MessageId, UserId}, ReplyHandle}; use serde_json::{json, Map, Value}; -use crate::{data::{self, get_mutex_data}, lang, messages::{edit_reply, embed_from_options, http_send_embed, make_post_embed, make_removed_embed, send_msg}, websocket::send_cmd_json, Context, Error, BK_WEEK}; +use crate::{data::{self, get_mutex_data, DC_POSTS_CHANNEL_KEY}, lang, messages::{edit_reply, embed_from_options, http_send_embed, make_post_embed, make_removed_embed, send_msg}, websocket::send_cmd_json, Context, Error, CFG_DATA_RE}; #[poise::command( slash_command, @@ -27,7 +27,7 @@ pub async fn cmd( { let http = ctx.http(); - let mut p_text = "`/bk_week_update`:".to_string(); + let mut p_text = "`/re_updatediscord`:".to_string(); let progress = send_msg(ctx, p_text.clone(), true, true).await.unwrap(); p_text = update_progress(ctx, progress.clone(), p_text, "\nFetching new posts & updating data file...".to_string()).await; @@ -42,7 +42,7 @@ pub async fn cmd( let c_id_u = get_c_id(ctx).await; if c_id_u.is_none() { - send_msg(ctx, "Could not find bk_week_channel in data!\nHint: Run (or tell an admin to run) `/bk_admin_bind` in a (preferably read-only) channel.".to_string(), true, true).await; + send_msg(ctx, lang!("dc_msg_re_posts_channel_404"), true, true).await; return Ok(()); } @@ -58,7 +58,7 @@ pub async fn cmd( // Adding new posts p_text = update_progress(ctx, progress.clone(), p_text.clone(), "✅\nAdding new posts...".to_string()).await; - let weekly_art = r_data[BK_WEEK].as_object().unwrap(); + let weekly_art = r_data[CFG_DATA_RE].as_object().unwrap(); add_posts(http, c_id, weekly_art, &msgs_json, max_age_secs).await; // Stop if only_add @@ -113,7 +113,7 @@ async fn get_c_id(ctx: Context<'_>) -> Option { let c_id_u = d["servers"] [ctx.guild_id().unwrap().to_string()] - ["bk_week_channel"].as_u64().unwrap(); + [DC_POSTS_CHANNEL_KEY].as_u64().unwrap(); let c_id = ChannelId::new(c_id_u); @@ -187,7 +187,7 @@ async fn msgs_to_json(msgs: Vec, reddit_data: &Value, max_age: u64) -> if msg_json.is_err() { continue; } let mut u_json: Value = msg_json.unwrap(); - let re_url = &reddit_data[BK_WEEK][&url]; + let re_url = &reddit_data[CFG_DATA_RE][&url]; let post_date = re_url["post_data"]["date_unix"].as_u64().unwrap_or(0); diff --git a/src/re_cmds/vote.rs b/src/re_cmds/vote.rs index 6cb05ad..f6549e4 100644 --- a/src/re_cmds/vote.rs +++ b/src/re_cmds/vote.rs @@ -1,6 +1,6 @@ use serde_json::json; -use crate::{data::{self, get_mutex_data}, lang, messages::send_msg, re_cmds::generic_fns::{is_bk_mod, send_embed_for_removed}, websocket::send_cmd_json, Context, Error, BK_WEEK}; +use crate::{data::{self, get_mutex_data}, lang, messages::send_msg, re_cmds::generic_fns::{is_bk_mod, send_embed_for_removed}, websocket::send_cmd_json, Context, Error, CFG_DATA_RE}; #[poise::command( slash_command, @@ -19,7 +19,7 @@ pub async fn cmd( data::update_re_data(ctx.data()).await; let uid = ctx.author().id.get(); let re_data = get_mutex_data(&ctx.data().reddit_data).await?; - let post_data = re_data[BK_WEEK].clone(); + let post_data = re_data[CFG_DATA_RE].clone(); let unw_vote = un_vote.unwrap_or(false); if post_data.get(&url).is_none() { diff --git a/src/schedule.rs b/src/schedule.rs index 0ab5cbd..6f915ba 100644 --- a/src/schedule.rs +++ b/src/schedule.rs @@ -5,7 +5,7 @@ use std::time::Duration; use tokio::task::JoinHandle; use tokio::time; -use crate::{lang, rs_println}; +use crate::rs_println; pub type Schedule = (Duration, fn() -> Pin + Send>>);