diff --git a/data/defaults/cfg_default.toml b/data/defaults/cfg_default.toml index d0e85a0..3ba1e6e 100644 --- a/data/defaults/cfg_default.toml +++ b/data/defaults/cfg_default.toml @@ -11,6 +11,10 @@ subreddits = "bytedicetesting" # How many posts the bot scans when running `/re_updatediscord`. fetch_limit = 100 +# A list of flairs the post must be tagged under to be scraped. +# Leave empty to search for everything +search_flairs = ["Original Art"] + [commands] # Disabled selected command categories. All commands and their categories can be viewed in the README. # "admin" and "owner" categories are always enabled. diff --git a/src/cmds/reload_cfg.rs b/src/cmds/reload_cfg.rs index e874040..e9400f9 100644 --- a/src/cmds/reload_cfg.rs +++ b/src/cmds/reload_cfg.rs @@ -21,7 +21,9 @@ pub async fn cmd( let d_str = toml::to_string(&d)?; let r = send_cmd_json("update_cfg", Some(json!([d_str])), true).await; - if r.is_some() && r.unwrap()["value"].as_bool().unwrap() { + if r.is_none() { return Ok(()); } + + if r.unwrap()["value"].as_bool().unwrap() { send_msg( ctx, lang!("dc_msg_reload_cfg_success", toml::to_string_pretty(&d).unwrap()), diff --git a/src/data.rs b/src/data.rs index 28437ec..ff51ca3 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, CFG_DATA_RE, LANG}; +use crate::{errln, rs_println, Data, Error, CFG_DATA_RE, LANG, LANG_NAME}; use crate::websocket::send_cmd_json; @@ -220,9 +220,10 @@ pub fn load_lang_data(lang: String) { } let str_data = fs::read_to_string(full_path).unwrap(); - let json_data = serde_json::from_str(&str_data).unwrap(); + let json_data: Option = serde_json::from_str(&str_data).unwrap(); unsafe { LANG = json_data; + LANG_NAME = Some(lang); }; } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index ccbe105..da0efba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,8 +95,9 @@ struct Data { static CFG_DATA_RE: &str = "posts"; -pub static mut LANG: Option = None; -pub static mut NOPING: bool = false; +pub static mut LANG_NAME: Option = None; +pub static mut LANG: Option = None; +pub static mut NOPING: bool = false; #[tokio::main] diff --git a/src/python.rs b/src/python.rs index 09b9a4f..89c96c3 100644 --- a/src/python.rs +++ b/src/python.rs @@ -1,5 +1,5 @@ use crate::messages::send_dm; -use crate::{errln, lang, rs_println, Args}; +use crate::{errln, lang, rs_println, Args, LANG_NAME}; use std::fs; use std::ffi::CString; @@ -21,7 +21,17 @@ pub async fn start(args: Args) -> PyResult<()> { let code = get_code(&format!("{}{}main.py", path, slash)); let py_args = args_str.replace(":true", ":True").replace(":false", ":False"); - let app_path = CString::new(format!("args = {}\n{}", py_args, code)).unwrap(); + let app_path: CString; + + unsafe { + app_path = CString::new( + format!("args = {}\nlang_name = {}\n{}", + py_args, + LANG_NAME.clone().unwrap(), + code + ) + ).unwrap(); + } let mut traceback: String = String::new(); let mut is_error = false; diff --git a/src/python/bot.py b/src/python/bot.py index e939470..0d1dc92 100644 --- a/src/python/bot.py +++ b/src/python/bot.py @@ -41,6 +41,7 @@ class Bot: self.sr = None self.data_f: TextIOWrapper = None self.data: dict = {} + self.flairs: list[str] = [] async def initialize(self): self.sr = await self.r.subreddit("+".join(self.sr_list)) @@ -58,13 +59,12 @@ class Bot: async def update_cfg_str(self, new_cfg: str) -> bool: json_cfg = toml.loads(new_cfg) - self.sr_list = json_cfg[CFG_DATA_RE]["subreddits"].split("+") - self.sr = await self.r.subreddit("+".join(self.sr_list)) - self.fetch_limit = json_cfg[CFG_DATA_RE]["fetch_limit"] + self.update_cfg(json_cfg) return True async def update_cfg(self, new_cfg: dict) -> bool: self.sr_list = new_cfg[CFG_DATA_RE]["subreddits"].split("+") self.sr = await self.r.subreddit("+".join(self.sr_list)) self.fetch_limit = new_cfg[CFG_DATA_RE]["fetch_limit"] + self.flairs = new_cfg[CFG_DATA_RE]["search_flair"] return True \ No newline at end of file diff --git a/src/python/macros.py b/src/python/macros.py index 239822d..3518f80 100644 --- a/src/python/macros.py +++ b/src/python/macros.py @@ -1,5 +1,13 @@ +import json +import os from printColors import PrintColors + +G_LANG_NAME: str = "" +G_LANG: dict[str, str] = {} +DATA_PATH_LANG: str = "./data/lang/" + + def py_print(*args): print( PrintColors.FG.blue + "Py", @@ -14,4 +22,30 @@ def py_error(*args): "-", " ".join(args) + PrintColors.Special.reset ) - quit() \ No newline at end of file + quit() + + +def lang(k: str) -> str: + t = G_LANG.get(k) + if k is None: py_error(f"Key not found in language \"{G_LANG_NAME}\": {k}") + return str(t) + + +def init_lang(lang_name: str): + global G_LANG, G_LANG_NAME + G_LANG_NAME = lang_name + + full_path = f"{DATA_PATH_LANG}{lang_name}.json" + + if not os.path.exists(full_path): + py_error(f"File for language \"{lang_name}\" ({lang_name}.json) not found!\n Hint: You can download official language files at https://github.com/ByteDice/ByteDiceAssistant in the data/langs/... folder") + + with open(full_path, "r") as f: + str_data = f.read() + + try: + json_data = json.loads(str_data) + except json.JSONDecodeError as e: + py_error(f"Failed to parse JSON for language \"{lang_name}\":\n{e}") + + G_LANG = json_data \ No newline at end of file diff --git a/src/python/main.py b/src/python/main.py index 72f32b9..8cf8ce3 100644 --- a/src/python/main.py +++ b/src/python/main.py @@ -19,9 +19,12 @@ async def main(): # args is supposed to be undefined. # It gets defined in Rust. - try: await bot.set_args(args) + try: + await bot.set_args(args) + init_lang(lang_name) except NameError: - py_print("No command args found from Rust. Don't worry though, we have backup in place.") + py_print("No command args or language name found from Rust. Don't worry though, we have backup in place.") + init_lang("en") if bot.args["dev"]: py_print("ARGS:", str(bot.args)) diff --git a/src/python/posts.py b/src/python/posts.py index 9a08a9e..f9651a7 100644 --- a/src/python/posts.py +++ b/src/python/posts.py @@ -14,7 +14,7 @@ async def add_new_posts(bot: botPy.Bot, max_age: int) -> bool: cross_emoji = emoji.emojize(":cross_mark:") py_print("Fetching posts...") - posts = await fetch_posts_with_flair(bot, "Original Art") + posts = await fetch_posts_with_flair(bot, bot.flairs) py_print("Evaluating posts...") @@ -65,11 +65,15 @@ async def add_new_posts(bot: botPy.Bot, max_age: int) -> bool: return True -async def fetch_posts_with_flair(bot: botPy.Bot, flair_name: str) -> list[models.Submission]: +async def fetch_posts_with_flair(bot: botPy.Bot, flair_names: list[str]) -> list[models.Submission]: posts: list[models.Submission] = [] + flair_names_str = \ + f"flair:{flair_names[0]}" if len(flair_names) == 1\ + else " OR ".join(f"flair:{flair}" for flair in flair_names) + # ~36 OG-art posts per week, round limit to 50, 75 or 100 - async for post in bot.sr.search(f"flair:\"{flair_name}\"", sort="new", limit=bot.fetch_limit): + async for post in bot.sr.search(f"{flair_names_str}", sort="new", limit=bot.fetch_limit): posts.append(post) return posts diff --git a/src/python/py_websocket.py b/src/python/py_websocket.py index 08279dd..94b9e70 100644 --- a/src/python/py_websocket.py +++ b/src/python/py_websocket.py @@ -7,6 +7,7 @@ import bot as botPy import data import posts import cmds +import macros ws_global = None is_connected = False @@ -74,16 +75,16 @@ async def json_to_func(v: dict, bot: botPy.Bot) -> dict: r = False match v["value"]: - case "update_data_file": r = data .write_data (bot) - case "respond_mentions": r = await cmds .respond_to_mention(bot) - case "add_new_posts": r = await posts.add_new_posts (bot, *v["args"]) - case "add_post_url": r = await posts.add_post_url (bot, *v["args"]) - case "remove_post_url": r = data .remove_post (bot, *v["args"]) - case "set_approve_post": r = data .set_approve_post (bot, *v["args"]) - case "set_vote_post": r = data .set_vote_post (bot, *v["args"]) - case "remove_old_posts": r = data .remove_old_posts (bot, *v["args"]) - case "update_cfg": r = await bot .update_cfg_str (*v["args"]) - case "stop_praw": r = await bot .stop () + case "update_data_file": r = data .write_data (bot) + case "respond_mentions": r = await cmds .respond_to_mention(bot) + case "add_new_posts": r = await posts .add_new_posts (bot, *v["args"]) + case "add_post_url": r = await posts .add_post_url (bot, *v["args"]) + case "remove_post_url": r = data .remove_post (bot, *v["args"]) + case "set_approve_post": r = data .set_approve_post (bot, *v["args"]) + case "set_vote_post": r = data .set_vote_post (bot, *v["args"]) + case "remove_old_posts": r = data .remove_old_posts (bot, *v["args"]) + case "update_cfg": r = await bot .update_cfg_str (*v["args"]) + case "stop_praw": r = await bot .stop () case _: value_supported = False print_result = v["print"] diff --git a/src/websocket.rs b/src/websocket.rs index 764d5c9..3b2a0f4 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -70,7 +70,7 @@ pub async fn send_cmd_json(func_name: &str, func_args: Option, print_outp { return r; } } - if !["respond_mentions"].contains(&func_name) || ::parse().dev { + if ::parse().dev { rs_println!("Received from Python: [RESPONSE] {:?}", r); }