From 2a10508534e091c2cf60bb86fc5eceee21e4e0b3 Mon Sep 17 00:00:00 2001 From: ByteDice Date: Thu, 13 Feb 2025 17:44:25 +0100 Subject: [PATCH] uhhhh. Update sized update --- TODO.md | 24 ++++++++++++------------ src/bk_week_cmds.rs | 36 +++++++++++++++++++++++++++++------- src/data.rs | 12 ++++++++---- src/main.rs | 8 +++++--- src/python/data.py | 11 ++++++++--- src/python/main.py | 25 ++++++++++++++++--------- src/python/posts.py | 5 +++-- src/python/py_websocket.py | 20 ++++++++++++++------ src/websocket.rs | 3 +++ 9 files changed, 98 insertions(+), 46 deletions(-) diff --git a/TODO.md b/TODO.md index 6c76eda..8ae2467 100644 --- a/TODO.md +++ b/TODO.md @@ -1,20 +1,20 @@ ### High priority: -- [x] ~~Embed creation tool~~ + - [ ] Reddit bot that scrapes images with tag "Original Art" and posts them in Discord server - - [x] ~~Discord bot /bk_help command~~ - - [x] ~~Scrape the data~~ - - [x] ~~Put it in a JSON~~ - - [x] ~~Multithread so it can run both Discord and Reddit bot!!!~~ + + + + - [ ] Allow updating the data autonomously and via manual commands. - [ ] Manually add posts - [ ] via `u/[bot] add` - - [x] ~~via `/bk_week_add [url]`~~ + - [ ] Manually remove posts via `/bk_week_remove [url]` - - [x] ~~Manually approve posts via `/bk_week_approve [url]`~~ + - [ ] Manually un-approve posts via `/bk_week_disapprove [url]` - - [x] ~~Automatically add scraped posts to JSON~~ + - [ ] Automatically remove posts older than 7 days from JSON - - [x] ~~Function~~ + - [ ] Automate - [ ] Automatically approve posts that dont get caught by reverse image search (ris) - [ ] Log all posts in a Discord thread @@ -24,10 +24,10 @@ - [ ] Remove post if its `"removed": true` in data - [ ] Add posts to data from channel - [ ] `/bk_week_update` to forcefully trigger this ^ - - [x] ~~`/bk_week_get [url]` get the data of a single post from the data~~ + ### Medium priority: -- [x] ~~JSON -> Rules list~~ + - [ ] View single rule (/rule {rulename}) - [ ] Postfix calculator - [ ] Postfic generator @@ -35,7 +35,7 @@ - [ ] BPS args -> JSON - [ ] Random tip (from ByteDice.net/data/loadingScreenTips.json) - [ ] A command that just sends my socials -- [x] ~~Magic 8 ball~~ + ### Low priority: - [ ] Particle of the week diff --git a/src/bk_week_cmds.rs b/src/bk_week_cmds.rs index 880cd53..a72302a 100644 --- a/src/bk_week_cmds.rs +++ b/src/bk_week_cmds.rs @@ -46,7 +46,8 @@ pub async fn bk_week_help( pub async fn bk_week_get( ctx: Context<'_>, #[description = "The post URL"] url: String -) -> Result<(), Error> { +) -> Result<(), Error> +{ data::update_re_data(ctx.data()).await; let reddit_data = get_reddit_data(ctx).await?; @@ -167,12 +168,17 @@ pub async fn bk_week_add( #[description = "Wether to approve it after adding it"] approve: Option ) -> Result<(), Error> { - // TODO: auto approve data::update_re_data(ctx.data()).await; let reddit_data = get_reddit_data(ctx).await.unwrap(); if let Some(bk_week) = reddit_data.get(BK_WEEK) { - websocket::send_cmd_json("add_post_url", json!([&url])).await; + let a = approve.unwrap_or_else(|| false); + let r = websocket::send_cmd_json("add_post_url", json!([&url, a])).await.unwrap(); + + if !r["value"].as_bool().unwrap() { + send_msg(ctx, "Unknown error!\nError trace: `bk_week_cmds.rs -> bk_week_add() -> Unknown error`.".to_string(), true, true).await; + return Ok(()); + } if let Some(post) = bk_week.get(&url) { if post.get("removed").is_some() { @@ -182,6 +188,13 @@ pub async fn bk_week_add( send_updated_msg(ctx, &url).await; } } + else { + send_msg(ctx, format!("Added post with URL \"<{}>\"!", &url), true, true).await; + } + + if a { + send_msg(ctx, "Also approved it!".to_string(), true, true).await; + } } return Ok(()); @@ -221,12 +234,19 @@ pub async fn bk_week_approve( data::update_re_data(ctx.data()).await; let reddit_data = get_reddit_data(ctx).await.unwrap(); + approve_cmd(ctx, &url, &reddit_data, true).await; + + return Ok(()); +} + + +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; } - let r = websocket::send_cmd_json("set_approve_post", json!([true, &url])).await; + let r = websocket::send_cmd_json("set_approve_post", json!([approve, &url])).await; if let Some(v) = r.unwrap().get("value") { send_msg(ctx, format!("Successfully flagged URL \"<{}>\" as `approved:by_human`!", &url), true, true).await; } @@ -237,18 +257,20 @@ pub async fn bk_week_approve( else { send_post_not_found_message(ctx, &url).await; } - - return Ok(()); } - #[poise::command(slash_command, prefix_command)] pub async fn bk_week_disapprove( ctx: Context<'_>, #[description = "The post URL"] url: String ) -> Result<(), Error> { + data::update_re_data(ctx.data()).await; + let reddit_data = get_reddit_data(ctx).await.unwrap(); + + approve_cmd(ctx, &url, &reddit_data, false).await; + return Ok(()); } \ No newline at end of file diff --git a/src/data.rs b/src/data.rs index ad102ce..cf55bcd 100644 --- a/src/data.rs +++ b/src/data.rs @@ -3,7 +3,7 @@ use std::path::Path; use serde_json::{self, Value, json}; -use crate::{Data, BK_WEEK}; +use crate::{Data, BK_WEEK, rs_println}; use crate::websocket::send_cmd_json; @@ -57,8 +57,12 @@ pub fn write_dc_data(data: &Data) { } -pub fn read_re_data(data: &Data) { - if !Path::new(DATA_PATH_RE).exists() { +pub fn read_re_data(data: &Data, wipe: bool) { + if !Path::new(DATA_PATH_RE).exists() || wipe { + rs_println!( + "{} creating new from preset...", + if !wipe { "reddit_data.json not found," } else { "[WIPE] (reddit_data.json)" } + ); generate_re_data(); } @@ -87,7 +91,7 @@ fn generate_re_data() { pub async fn update_re_data(data: &Data) { send_cmd_json("update_data_file", json!([])).await; - read_re_data(data); + read_re_data(data, false); } diff --git a/src/main.rs b/src/main.rs index 55ac9da..60bf565 100644 --- a/src/main.rs +++ b/src/main.rs @@ -32,7 +32,9 @@ struct Args { #[arg(long, help = "Runs only the Rust part of the program.")] rs: bool, #[arg(short = 'd', long, help = "Enables dev mode. Dev mode shows more debug info and turns of certain security measures.")] - dev: bool + dev: bool, + #[arg(short = 'w', long, help = "Wipes all data before running the program.")] + wipe: bool } struct Data { @@ -111,11 +113,11 @@ fn gen_data(args: Args) -> Data { byte_dice_id: 697149665166229614, reddit_data: None.into(), discord_data: None.into(), - args + args: args.clone() }; data::read_dc_data(&data); - data::read_re_data(&data); + data::read_re_data(&data, args.clone().wipe); return data; } diff --git a/src/python/data.py b/src/python/data.py index ae778b1..830c09f 100644 --- a/src/python/data.py +++ b/src/python/data.py @@ -57,14 +57,17 @@ class PostData: } -def read_data(bot: botPy.Bot): +def read_data(bot: botPy.Bot) -> bool: # Intentionally unreadable >:] data_path = os.path.abspath(os.path.join(os.path.join(os.getcwd(), "data"))) - try: + if os.path.isfile(data_path + "\\reddit_data.json"): bot.data_f = open(data_path + "\\reddit_data.json", "r+") - except FileNotFoundError: + else: + if not bot.args["py"]: + return False + py_print("reddit_data.json not found, creating new from preset...") with open(data_path + "\\reddit_data_preset.json", "r") as f: data_preset_json = json.load(f) @@ -83,6 +86,8 @@ def read_data(bot: botPy.Bot): if not bot.data["file_created_correctly"]: raise Exception("reddit_data.json file wasn't created properly. Delete the file and retry.") + + return True def write_data(bot: botPy.Bot) -> bool: diff --git a/src/python/main.py b/src/python/main.py index eba1a58..44a4042 100644 --- a/src/python/main.py +++ b/src/python/main.py @@ -27,21 +27,28 @@ async def main(): if bot.args["dev"]: py_print("ARGS:", str(bot.args)) + py_print("Reading data...") - data.read_data(bot) + dr = data.read_data(bot) + data_retries = 0 + + while not dr: + data_retries += 1 + time.sleep(1) + py_print(f"Failed to read data: File doesn't exist yet. Retrying (#{data_retries}/5)...") + dr = data.read_data(bot) + + if data_retries == 5 and not dr: + raise Exception("Couldn't read reddit_data.json: File doesn't exist") + + py_print("Successfully read data!") if not bot.args["py"]: py_print("Connecting to local websocket...") await py_websocket.websocket_client(bot) - """ ws_thread = threading.Thread(target=py_websocket.run_thread, args=(bot,)) - ws_thread.start() """ - - while not py_websocket.is_connected: - py_print("Awaiting connection...") - time.sleep(1) - continue - await py_websocket.send_message("[Connection test] Hello from Python!") + # ws_thread = threading.Thread(target=py_websocket.run_thread, args=(bot,)) + # ws_thread.start() await bot.stop() diff --git a/src/python/posts.py b/src/python/posts.py index 37c0389..50fc9e3 100644 --- a/src/python/posts.py +++ b/src/python/posts.py @@ -43,7 +43,7 @@ async def add_new_posts(bot: botPy.Bot): if post_added: added_posts += 1 else: not_added += 1 - py_print(f"Sucessfully fetched {len(posts)} posts.\n" + + py_print(f"Successfully fetched {len(posts)} posts.\n" + f" Out of which were {added_posts} added.\n" + f" {without_media} had no media, " + f"and {not_added} weren't added because they are removed or already existed") @@ -114,11 +114,12 @@ def get_post_details(post: models.Submission) -> data.PostData: ) -async def add_post_url(bot, url: str) -> bool: +async def add_post_url(bot, url: str, approve: bool) -> bool: result, post = await from_url(bot, url) if not result: return result post_data = get_post_details(post) + post_data.approved_by_human = approve return data.add_post_to_data(bot, post_data, True) \ No newline at end of file diff --git a/src/python/py_websocket.py b/src/python/py_websocket.py index 7be9a91..6e2358e 100644 --- a/src/python/py_websocket.py +++ b/src/python/py_websocket.py @@ -2,7 +2,7 @@ import websockets import asyncio import json -from macros import py_print +from macros import * import bot as botPy import data import posts @@ -18,10 +18,13 @@ async def send_message(message: str): async def websocket_client(bot: botPy.Bot): global ws_global, is_connected - async with websockets.connect(f"ws://127.0.0.1:{bot.args["port"]}") as ws: + port = bot.args["port"] + async with websockets.connect(f"ws://127.0.0.1:{port}") as ws: ws_global = ws is_connected = True - py_print(f"Connected webSocket server on ws://127.0.0.1:{bot.args["port"]}") + py_print(f"Connected webSocket server on ws://127.0.0.1:{port}") + + await send_message("[Connection test] Hello from Python!") while True: response = await ws.recv() @@ -52,7 +55,8 @@ async def json_to_func(v: dict, bot: botPy.Bot) -> dict: if bot.args["dev"]: py_print("JSON is not a dictionary or does not include \"type\" and \"value\" keys.") return if v["type"] != "function": - if bot.args["dev"]: py_print(f"Type \"{v['type']}\" is not supported.") + v_type = v["type"] + if bot.args["dev"]: py_print(f"Type \"{v_type}\" is not supported.") return value_supported = True @@ -62,11 +66,15 @@ async def json_to_func(v: dict, bot: botPy.Bot) -> dict: case "update_data_file": result = result_json(data.write_data(bot)) case "add_post_url": result = result_json(await posts.add_post_url(bot, *v["args"])) case "set_approve_post": result = result_json(data.set_approve_post(bot, *v["args"])) - case "stop_praw": result = result_json(bot.stop()) + case "stop_praw": result = result_json(await bot.stop()) case _: value_supported = False + if not isinstance(result.get("value"), bool): + py_print("Result JSON is invalid:", str(result)) + if bot.args["dev"] and not value_supported: - py_print(f"Value {v['value']} is not supported") + val = v["value"] + py_print(f"Value \"{val}\" is not supported") return result diff --git a/src/websocket.rs b/src/websocket.rs index 0dff001..d0b098d 100644 --- a/src/websocket.rs +++ b/src/websocket.rs @@ -31,6 +31,7 @@ async fn set_receiver(receiver: Receiver) { } +#[allow(static_mut_refs)] pub async fn send_msg(msg: &str) { unsafe { if let Some(sender) = &GLOBAL_SENDER { @@ -43,6 +44,7 @@ pub async fn send_msg(msg: &str) { } +#[allow(static_mut_refs)] pub async fn send_cmd_json(func_name: &str, func_args: Value) -> Option { unsafe { let Some(sender) = &GLOBAL_SENDER else { return None }; @@ -65,6 +67,7 @@ pub async fn send_cmd_json(func_name: &str, func_args: Value) -> Option { } +#[allow(static_mut_refs)] async fn receive_response() -> Option { unsafe { let Some(receiver) = &GLOBAL_RECEIVER else { return None };