This commit is contained in:
2025-02-21 16:48:16 +01:00
parent 1873a22e23
commit d82e455bd5
8 changed files with 192 additions and 106 deletions
+1
View File
@@ -11,6 +11,7 @@ An automation tool for Byte Dice. It's both a Discord and Reddit bot in one prog
## How to run ## How to run
**Dependecies:** 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: **Dependecies:** 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:
<!-- TODO: update with all python modules (not just external) -->
* sys * sys
* io * io
* asyncpraw * asyncpraw
+1 -1
View File
@@ -9,7 +9,7 @@
<!-- - [x] Some kind of voting system. --> <!-- - [x] Some kind of voting system. -->
- [ ] `/bk_week_top [category] [amount]` to get the top N posts in a category (e.g upvotes) - [ ] `/bk_week_top [category] [amount]` to get the top N posts in a category (e.g upvotes)
- [ ] Allow updating the data autonomously and via manual commands. - [ ] Allow updating the data autonomously and via manual commands.
- [ ] 10-minute schedule for updating Discord channel <!-- - [ ] 10-minute schedule for updating Discord channel (IMPOSSIBLE / REALLY FUCKING HARD) -->
<!-- - [x] ~~Manually add posts~~ --> <!-- - [x] ~~Manually add posts~~ -->
<!-- - [x] ~~via `u/[bot] add`~~ --> <!-- - [x] ~~via `u/[bot] add`~~ -->
<!-- - [x] ~~via `/bk_week_add [url]`~~ --> <!-- - [x] ~~via `/bk_week_add [url]`~~ -->
+112 -74
View File
@@ -1,13 +1,12 @@
use crate::websocket::send_cmd_json; use crate::websocket::send_cmd_json;
use crate::{rs_println, websocket, Context, Error, BK_WEEK}; use crate::{rs_println, websocket, Context, Data, Error, BK_WEEK};
use crate::messages::{edit_msg, embed_from_options, embed_post, embed_post_removed, send_embed, send_msg}; use crate::messages::*;
use crate::data::{self, dc_bind_bk}; use crate::data::{self, dc_bind_bk};
use std::fs; use std::fs;
use poise::serenity_prelude::{ChannelId, EditMessage, GetMessages, Message, MessageId}; use poise::serenity_prelude::{ChannelId, EditMessage, GetMessages, Http, Message, MessageId, UserId};
use poise::ReplyHandle; use serde_json::{json, Map, Value};
use serde_json::{json, Value};
#[derive(poise::ChoiceParameter, PartialEq)] #[derive(poise::ChoiceParameter, PartialEq)]
@@ -71,7 +70,7 @@ pub async fn bk_week_get(
{ {
data::update_re_data(ctx.data()).await; data::update_re_data(ctx.data()).await;
let reddit_data = get_reddit_data(ctx).await?; let reddit_data = get_reddit_data(ctx.data()).await?;
if let Some(post) = get_post_from_data(ctx, &reddit_data, &url).await? { if let Some(post) = get_post_from_data(ctx, &reddit_data, &url).await? {
send_embed_for_post(ctx, post, &url).await?; send_embed_for_post(ctx, post, &url).await?;
@@ -80,8 +79,8 @@ pub async fn bk_week_get(
return Ok(()); return Ok(());
} }
async fn get_reddit_data(ctx: Context<'_>) -> Result<Value, Error> { pub async fn get_reddit_data(data: &Data) -> Result<Value, Error> {
let data_lock = ctx.data().reddit_data.lock().await; let data_lock = data.reddit_data.lock().await;
return match data_lock.as_ref() { return match data_lock.as_ref() {
Some(data) => Ok(data.clone()), Some(data) => Ok(data.clone()),
None => Err("Reddit data is corrupted".into()), None => Err("Reddit data is corrupted".into()),
@@ -174,7 +173,7 @@ pub async fn bk_week_add(
} }
data::update_re_data(ctx.data()).await; data::update_re_data(ctx.data()).await;
let reddit_data = get_reddit_data(ctx).await.unwrap(); let reddit_data = get_reddit_data(ctx.data()).await.unwrap();
if let Some(bk_week) = reddit_data.get(BK_WEEK) { if let Some(bk_week) = reddit_data.get(BK_WEEK) {
let a = approve.unwrap_or_else(|| false); let a = approve.unwrap_or_else(|| false);
@@ -273,7 +272,7 @@ pub async fn bk_week_approve(
} }
data::update_re_data(ctx.data()).await; data::update_re_data(ctx.data()).await;
let reddit_data = get_reddit_data(ctx).await.unwrap(); let reddit_data = get_reddit_data(ctx.data()).await.unwrap();
approve_cmd(ctx, &url, &reddit_data, !disapprove.unwrap_or_else(|| false)).await; approve_cmd(ctx, &url, &reddit_data, !disapprove.unwrap_or_else(|| false)).await;
@@ -317,7 +316,7 @@ pub async fn bk_admin_bind(
let c_id = ctx.channel_id().into(); let c_id = ctx.channel_id().into();
let r = dc_bind_bk(ctx.data(), ctx.guild_id().unwrap().into(), c_id).await; let r = dc_bind_bk(ctx.data(), ctx.guild_id().unwrap().into(), c_id).await;
if r { if r.is_ok() {
send_msg(ctx, format!("Successfully bound channel ID `{}` as the bk_week channel!", c_id), true, true).await; send_msg(ctx, format!("Successfully bound channel ID `{}` as the bk_week channel!", c_id), true, true).await;
} }
else { else {
@@ -342,89 +341,80 @@ pub async fn bk_week_update(
#[description = "Only adds new posts, leaves everything else unchanged."] only_add: Option<bool> #[description = "Only adds new posts, leaves everything else unchanged."] only_add: Option<bool>
) -> Result<(), Error> ) -> Result<(), Error>
{ {
let mut p_text = "Fetching new posts & updating data file...".to_string(); let http = ctx.http();
let progress = send_msg(ctx, p_text.clone(), true, true).await;
let executed = format!("(Executed `/bk_week_update`, author: `{}`)", ctx.author().name);
let mut p_text = executed.clone();
send_msg(ctx, MANDATORY_MSG.to_string(), true, true).await;
let progress = http_send_msg(http, ctx.channel_id(), p_text.clone()).await.unwrap();
p_text = update_progress(ctx.http(), progress.clone(), p_text, "\nFetching new posts & updating data file...".to_string()).await;
send_cmd_json("add_new_posts", None).await; send_cmd_json("add_new_posts", None).await;
data::update_re_data(ctx.data()).await; data::update_re_data(ctx.data()).await;
let r_data = get_reddit_data(ctx).await.unwrap(); let r_data = get_reddit_data(ctx.data()).await.unwrap();
let c_id = get_c_id(ctx).await.unwrap_or_else(|| 0); let c_id_u = get_c_id(ctx).await;
if c_id == 0 { 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, "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;
return Ok(()); return Ok(());
} }
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), format!("\nReading messages in <#{}>...", c_id)).await; let c_id = c_id_u.unwrap();
let msgs = read_msgs(ctx, c_id).await;
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "\nParsing messages to JSON...".to_string()).await; // Reading messages
p_text = update_progress(http, progress.clone(), p_text.clone(), format!("\nReading messages in <#{}>...", c_id)).await;
let msgs = read_msgs(http, ctx.framework().bot_id, c_id).await;
// Parsing messages to JSON
p_text = update_progress(http, progress.clone(), p_text.clone(), "\nParsing messages to JSON...".to_string()).await;
let msgs_json = msgs_to_json(msgs, &r_data).await; let msgs_json = msgs_to_json(msgs, &r_data).await;
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "\nAdding new posts...".to_string()).await; // Adding new posts
p_text = update_progress(http, 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[BK_WEEK].as_object().unwrap();
add_posts(http, c_id, weekly_art, &msgs_json).await;
for url in weekly_art.keys() { // Stop if only_add
if ["no_change", "updated", "removed"]
.iter()
.any(|key| msgs_json[key].as_object().unwrap().contains_key(url))
{ continue; }
if msgs_json["duplicates"].as_object().unwrap().contains_key(url) { continue; }
if weekly_art[url].get("removed").is_some() {
send_embed(ctx, embed_post_removed(&weekly_art[url], url, false), false).await;
continue;
}
send_embed(ctx, embed_post(&weekly_art[url], url, false), false).await;
}
if only_add.unwrap_or_else(|| false) { if only_add.unwrap_or_else(|| false) {
update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "\n## Done!".to_string()).await; send_msg(ctx, "`/bk_week_update`\n## Done!".to_string(), true, true).await;
update_progress(http, progress.clone(), String::new(), executed).await;
return Ok(()); return Ok(());
} }
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "\nEditing updated posts...".to_string()).await; // Editing updated posts
for (url, msg_id) in msgs_json["updated"].as_object().unwrap() { p_text = update_progress(http, progress.clone(), p_text.clone(), "\nEditing updated posts...".to_string()).await;
let mut msg = ctx.http().get_message(ctx.channel_id(), MessageId::new(msg_id.as_u64().unwrap())).await.unwrap(); edit_posts(http, c_id, weekly_art, &msgs_json).await;
let r = EditMessage::new()
.embeds(vec![embed_from_options(embed_post(&weekly_art[url], url, false))]);
let _ = msg.edit(ctx, r).await; // Removing removed posts
} p_text = update_progress(http, progress.clone(), p_text.clone(), "\nRemoving removed posts...".to_string()).await;
remove_posts(http, c_id, weekly_art, &msgs_json).await;
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "\nRemoving removed posts...".to_string()).await; // Removing duplicate posts
for (url, msg_id) in msgs_json["removed"].as_object().unwrap() { update_progress(http, progress.clone(), p_text.clone(), "\nRemoving duplicate posts...".to_string()).await;
let mut msg = ctx.http().get_message(ctx.channel_id(), MessageId::new(msg_id.as_u64().unwrap())).await.unwrap(); remove_dupes(http, c_id, &msgs_json).await;
let r = EditMessage::new()
.embeds(vec![embed_from_options(embed_post_removed(&weekly_art[url], url, false))]);
let _ = msg.edit(ctx, r).await; // Done
} send_msg(ctx, "`/bk_week_update`\n## Done!".to_string(), true, true).await;
update_progress(http, progress.clone(), String::new(), executed).await;
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "\nRemoving duplicate posts...".to_string()).await;
for (_url, msgs) in msgs_json["duplicates"].as_object().unwrap() {
for msg_id in msgs.as_array().unwrap() {
let msg = ctx.http().get_message(ctx.channel_id(), MessageId::new(msg_id.as_u64().unwrap())).await.unwrap();
let _ = msg.delete(ctx.http()).await;
}
}
update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "\n## Done!".to_string()).await;
return Ok(()); return Ok(());
} }
async fn update_progress(ctx: Context<'_>, p: ReplyHandle<'_>, t: String, a_t: String) -> String { async fn update_progress(http: &Http, p: Message, t: String, added_t: String) -> String {
let p_text = format!("{} {}", t, a_t); let p_text = format!("{} {}", t, added_t);
edit_msg(ctx, p, p_text.clone()).await;
let new_msg = EditMessage::new().content(&p_text);
http_edit_msg(http, p, new_msg).await;
return p_text; return p_text;
} }
async fn get_c_id(ctx: Context<'_>) -> Option<u64> { async fn get_c_id(ctx: Context<'_>) -> Option<ChannelId> {
if !data::dc_contains_server(ctx.data(), ctx.guild_id().unwrap().into()).await { if !data::dc_contains_server(ctx.data(), ctx.guild_id().unwrap().into()).await {
send_server_not_in_data_msg(ctx).await; send_server_not_in_data_msg(ctx).await;
return None; return None;
@@ -432,27 +422,27 @@ async fn get_c_id(ctx: Context<'_>) -> Option<u64> {
let d_lock = ctx.data().discord_data.lock().await; let d_lock = ctx.data().discord_data.lock().await;
let d = d_lock.as_ref().unwrap(); let d = d_lock.as_ref().unwrap();
let c_id = let c_id_u =
d["servers"] d["servers"]
[ctx.guild_id().unwrap().to_string()] [ctx.guild_id().unwrap().to_string()]
["bk_week_channel"].as_u64().unwrap(); ["bk_week_channel"].as_u64().unwrap();
let c_id = ChannelId::new(c_id_u);
return Some(c_id); return Some(c_id);
} }
async fn read_msgs(ctx: Context<'_>, c_id: u64) -> Vec<Message> { pub async fn read_msgs(http: &Http, bot_id: UserId, c_id: ChannelId) -> Vec<Message> {
let c = ChannelId::new(c_id);
let b = GetMessages::new().limit(100); let b = GetMessages::new().limit(100);
let mut msgs = c.messages(ctx.http(), b).await.unwrap(); let mut msgs = c_id.messages(http, b).await.unwrap();
msgs = msgs.into_iter().filter(|item| item.author.id == ctx.framework().bot_id).collect(); msgs = msgs.into_iter().filter(|item| item.author.id == bot_id).collect();
let mut last_msg: Option<Message> = msgs.last().cloned(); let mut last_msg: Option<Message> = msgs.last().cloned();
while last_msg.is_some() { while last_msg.is_some() {
let new_b = GetMessages::new().limit(100).before(last_msg.clone().unwrap()); let new_b = GetMessages::new().limit(100).before(last_msg.clone().unwrap());
let new_msgs = c.messages(ctx.http(), new_b).await.unwrap(); let new_msgs = c_id.messages(http, new_b).await.unwrap();
last_msg = new_msgs.last().cloned(); last_msg = new_msgs.last().cloned();
@@ -462,7 +452,7 @@ async fn read_msgs(ctx: Context<'_>, c_id: u64) -> Vec<Message> {
let filtered_msgs: Vec<Message> = new_msgs let filtered_msgs: Vec<Message> = new_msgs
.into_iter() .into_iter()
.filter(|item| item.author.id == ctx.framework().bot_id) .filter(|item| item.author.id == bot_id)
.collect(); .collect();
msgs.extend(filtered_msgs); msgs.extend(filtered_msgs);
@@ -472,7 +462,7 @@ async fn read_msgs(ctx: Context<'_>, c_id: u64) -> Vec<Message> {
} }
async fn msgs_to_json<'a>(msgs: Vec<Message>, reddit_data: &'a Value) -> Value { pub async fn msgs_to_json<'a>(msgs: Vec<Message>, reddit_data: &'a Value) -> Value {
let mut msgs_json: Value = json!({"no_change": {}, "updated": {}, "removed": {}, "duplicates": {}}); let mut msgs_json: Value = json!({"no_change": {}, "updated": {}, "removed": {}, "duplicates": {}});
for msg in msgs { for msg in msgs {
@@ -542,6 +532,54 @@ async fn msgs_to_json<'a>(msgs: Vec<Message>, reddit_data: &'a Value) -> Value {
} }
pub async fn add_posts(http: &Http, c_id: ChannelId, r_data: &Map<String, Value>, msgs_json: &Value) {
for url in r_data.keys() {
if ["no_change", "updated", "removed"]
.iter()
.any(|key| msgs_json[key].as_object().unwrap().contains_key(url))
{ continue; }
if msgs_json["duplicates"].as_object().unwrap().contains_key(url) { continue; }
if r_data[url].get("removed").is_some() {
http_send_embed(http, c_id, embed_post_removed(&r_data[url], url, false)).await;
continue;
}
http_send_embed(http, c_id, embed_post(&r_data[url], url, false)).await;
}
}
pub async fn edit_posts(http: &Http, c_id: ChannelId, r_data: &Map<String, Value>, msgs_json: &Value) {
for (url, msg_id) in msgs_json["updated"].as_object().unwrap() {
let mut msg = http.get_message(c_id, MessageId::new(msg_id.as_u64().unwrap())).await.unwrap();
let r = EditMessage::new()
.embeds(vec![embed_from_options(embed_post(&r_data[url], url, false))]);
let _ = msg.edit(http, r).await;
}
}
pub async fn remove_posts(http: &Http, c_id: ChannelId, r_data: &Map<String, Value>, msgs_json: &Value) {
for (url, msg_id) in msgs_json["removed"].as_object().unwrap() {
let mut msg = http.get_message(c_id, MessageId::new(msg_id.as_u64().unwrap())).await.unwrap();
let r = EditMessage::new()
.embeds(vec![embed_from_options(embed_post_removed(&r_data[url], url, false))]);
let _ = msg.edit(http, r).await;
}
}
pub async fn remove_dupes(http: &Http, c_id: ChannelId, msgs_json: &Value) {
for (_url, msgs) in msgs_json["duplicates"].as_object().unwrap() {
for msg_id in msgs.as_array().unwrap() {
let msg = http.get_message(c_id, MessageId::new(msg_id.as_u64().unwrap())).await.unwrap();
let _ = msg.delete(http).await;
}
}
}
#[poise::command(slash_command, prefix_command)] #[poise::command(slash_command, prefix_command)]
@@ -554,7 +592,7 @@ pub async fn bk_week_vote(
{ {
data::update_re_data(ctx.data()).await; data::update_re_data(ctx.data()).await;
let uid = ctx.author().id.get(); let uid = ctx.author().id.get();
let re_data = get_reddit_data(ctx).await.unwrap(); let re_data = get_reddit_data(ctx.data()).await.unwrap();
let post_data = re_data[BK_WEEK].clone(); let post_data = re_data[BK_WEEK].clone();
let unw_vote = un_vote.unwrap_or_else(|| false); let unw_vote = un_vote.unwrap_or_else(|| false);
+5 -5
View File
@@ -3,7 +3,7 @@ use std::process;
use crate::data::dc_add_server; use crate::data::dc_add_server;
use crate::websocket::send_cmd_json; use crate::websocket::send_cmd_json;
use crate::{data, Context, Error}; use crate::{data, Context, Error};
use crate::messages::{edit_msg, send_embed, send_msg, Author, EmbedOptions}; use crate::messages::{edit_reply, send_embed, send_msg, Author, EmbedOptions, MANDATORY_MSG};
use poise::serenity_prelude::{OnlineStatus, Timestamp, UserId}; use poise::serenity_prelude::{OnlineStatus, Timestamp, UserId};
use rand::{seq::IteratorRandom, Rng}; use rand::{seq::IteratorRandom, Rng};
@@ -41,7 +41,7 @@ pub async fn stop(
data::write_re_data().await; data::write_re_data().await;
send_cmd_json("stop_praw", None).await; send_cmd_json("stop_praw", None).await;
edit_msg(ctx, msg, "Saving data... Done!\nShutting down...".to_string()).await; edit_reply(ctx, msg, "Saving data... Done!\nShutting down...".to_string()).await;
ctx.serenity_context().set_presence(None, OnlineStatus::Invisible); ctx.serenity_context().set_presence(None, OnlineStatus::Invisible);
ctx.framework().shard_manager.shutdown_all().await; ctx.framework().shard_manager.shutdown_all().await;
@@ -97,7 +97,7 @@ pub async fn embed(
).await; ).await;
if !reply_unwrap { if !reply_unwrap {
send_msg(ctx, "Mandatory success response, please ignore.".to_string(), true, true).await; send_msg(ctx, MANDATORY_MSG.to_string(), true, true).await;
} }
return Ok(()); return Ok(());
@@ -117,7 +117,7 @@ pub async fn send(
) -> Result<(), Error> ) -> Result<(), Error>
{ {
send_msg(ctx, msg.replace("\\n", "\n"), false, false).await; send_msg(ctx, msg.replace("\\n", "\n"), false, false).await;
send_msg(ctx, "Mandatory success response, please ignore.".to_string(), true, true).await; send_msg(ctx, MANDATORY_MSG.to_string(), true, true).await;
return Ok(()); return Ok(());
} }
@@ -186,7 +186,7 @@ pub async fn add_server(
{ {
let r = dc_add_server(ctx.data(), ctx.guild_id().unwrap().into()).await; let r = dc_add_server(ctx.data(), ctx.guild_id().unwrap().into()).await;
if r { if r.is_ok() {
send_msg(ctx, "Added your server to my data! Thanks for letting me steal it! (/s)".to_string(), true, true).await; send_msg(ctx, "Added your server to my data! Thanks for letting me steal it! (/s)".to_string(), true, true).await;
} }
else { else {
+12 -7
View File
@@ -55,6 +55,7 @@ pub async fn write_dc_data(data: &Data) {
.open(DATA_PATH_DC) .open(DATA_PATH_DC)
.unwrap(); .unwrap();
let mut dc_data_lock = data.discord_data.lock().await; let mut dc_data_lock = data.discord_data.lock().await;
let dc_data = dc_data_lock.as_mut().unwrap(); let dc_data = dc_data_lock.as_mut().unwrap();
let json_str = serde_json::to_string_pretty(dc_data).unwrap(); let json_str = serde_json::to_string_pretty(dc_data).unwrap();
@@ -106,39 +107,43 @@ pub async fn write_re_data() {
} }
pub async fn dc_add_server(data: &Data, server_id: u64) -> bool { pub async fn dc_add_server(data: &Data, server_id: u64) -> Result<(), ()> {
let mut dc_data_lock = data.discord_data.lock().await; let mut dc_data_lock = data.discord_data.lock().await;
let dc_data = dc_data_lock.as_mut().unwrap(); let dc_data = dc_data_lock.as_mut().unwrap();
if dc_data.get("servers").is_none() { return false; } if dc_data.get("servers").is_none() { return Err(()); }
let servers = dc_data["servers"].as_object_mut().unwrap(); let servers = dc_data["servers"].as_object_mut().unwrap();
if !servers.contains_key(&server_id.to_string()) { if !servers.contains_key(&server_id.to_string()) {
servers.insert(server_id.to_string(), json!({ "bk_week_channel": 0, "bk_mod_role": "bk mod", "bk_mods": [] })); servers.insert(server_id.to_string(), json!({ "bk_week_channel": 0, "bk_mod_role": "bk mod", "bk_mods": [] }));
} }
println!("moo");
write_dc_data(data).await;
println!("muu");
return true; return Ok(());
} }
pub async fn dc_bind_bk(data: &Data, server_id: u64, channel_id: u64) -> bool { pub async fn dc_bind_bk(data: &Data, server_id: u64, channel_id: u64) -> Result<(), ()> {
let mut dc_data_lock = data.discord_data.lock().await; let mut dc_data_lock = data.discord_data.lock().await;
let dc_data = dc_data_lock.as_mut().unwrap(); let dc_data = dc_data_lock.as_mut().unwrap();
if dc_data.get("servers").is_none() { return false; } if dc_data.get("servers").is_none() { return Err(()); }
let servers = dc_data["servers"].as_object_mut().unwrap(); let servers = dc_data["servers"].as_object_mut().unwrap();
if !servers.contains_key(&server_id.to_string()) { if !servers.contains_key(&server_id.to_string()) {
return false; return Err(());
} }
let server = servers[&server_id.to_string()].as_object_mut().unwrap(); let server = servers[&server_id.to_string()].as_object_mut().unwrap();
server.insert("bk_week_channel".to_string(), channel_id.into()); server.insert("bk_week_channel".to_string(), channel_id.into());
write_dc_data(data).await;
return true; return Ok(());
} }
+15 -12
View File
@@ -6,6 +6,7 @@ mod events;
mod messages; mod messages;
mod python; mod python;
mod macros; mod macros;
#[allow(unknown_lints)]
mod websocket; mod websocket;
mod data; mod data;
@@ -14,6 +15,7 @@ use std::pin::Pin;
use std::process; use std::process;
use std::thread; use std::thread;
use std::time::Duration; use std::time::Duration;
use std::vec;
use clap::Parser; use clap::Parser;
use poise::serenity_prelude as serenity; use poise::serenity_prelude as serenity;
@@ -46,7 +48,9 @@ struct Args {
#[arg(short = 't', long, help = "Makes the program use the ASSISTANT_TOKEN_TEST env var instead of ASSISTANT_TOKEN. This env var should hold the token of a non-production bot.")] #[arg(short = 't', long, help = "Makes the program use the ASSISTANT_TOKEN_TEST env var instead of ASSISTANT_TOKEN. This env var should hold the token of a non-production bot.")]
test: bool, test: bool,
#[arg(long, help = "Removes the annoying ping prints.")] #[arg(long, help = "Removes the annoying ping prints.")]
noping: bool noping: bool,
#[arg(long, help = "Makes the program not use the schedules.")]
nosched: bool
} }
@@ -75,6 +79,7 @@ async fn main() {
if args.test { println!("----- USING TEST BOT -----"); } if args.test { println!("----- USING TEST BOT -----"); }
if args.dev { println!("----- DEV MODE ENABLED -----"); } if args.dev { println!("----- DEV MODE ENABLED -----"); }
if args.dev && args.wipe { println!("----- \"DON'T WORRY ABOUT IT\" MODE ENABLED -----"); } if args.dev && args.wipe { println!("----- \"DON'T WORRY ABOUT IT\" MODE ENABLED -----"); }
if args.nosched { println!("----- NO SCHEDULES -----") }
if args.py && !args.rs { if args.py && !args.rs {
println!("----- PYTHON ONLY MODE -----"); println!("----- PYTHON ONLY MODE -----");
@@ -96,11 +101,12 @@ async fn main() {
let rt = Runtime::new().unwrap(); let rt = Runtime::new().unwrap();
let python_args = args_str; let python_args = args_str;
let rust_args = args.clone();
let rust = thread::spawn(move || { let rust = thread::spawn(move || {
rt.block_on(async { rt.block_on(async {
websocket::start(args.clone()).await; websocket::start(rust_args.clone()).await;
start(args).await; start(rust_args).await;
}); });
}); });
@@ -108,12 +114,13 @@ async fn main() {
let _ = python::start(python_args); let _ = python::start(python_args);
}); });
let schedules: Vec<(Duration, fn() -> Pin<Box<dyn Future<Output = ()> + Send>>)> = vec![ if !args.nosched {
(Duration::from_secs(/* 2 * 60 */ 30), || Box::pin(read_reddit_inbox())), let schedules: Vec<(Duration, fn() -> Pin<Box<dyn Future<Output = ()> + Send>>)> = vec![
(Duration::from_secs(/* 10 * 60 */ 60), || Box::pin(update_post_channels())) (Duration::from_secs(/* 2 * 60 */ 30), || Box::pin(read_reddit_inbox()))
]; ];
run_schedules(schedules).await; run_schedules(schedules).await;
}
rust.join().unwrap(); rust.join().unwrap();
python.join().unwrap(); python.join().unwrap();
@@ -237,7 +244,3 @@ async fn read_reddit_inbox() {
unsafe { if !websocket::HAS_CONNECTED { return; } } unsafe { if !websocket::HAS_CONNECTED { return; } }
send_cmd_json("respond_mentions", None).await; send_cmd_json("respond_mentions", None).await;
} }
async fn update_post_channels() {
println!("simulated update post channels");
}
+41 -2
View File
@@ -4,7 +4,7 @@ use crate::{Args, Context};
use poise::serenity_prelude::json::Value; use poise::serenity_prelude::json::Value;
use poise::{serenity_prelude::CreateMessage, CreateReply, ReplyHandle}; use poise::{serenity_prelude::CreateMessage, CreateReply, ReplyHandle};
use poise::serenity_prelude::{Color, CreateEmbed, CreateEmbedAuthor, Http, Timestamp, UserId}; use poise::serenity_prelude::{ChannelId, Color, CreateEmbed, CreateEmbedAuthor, EditMessage, Http, Message, Timestamp, UserId};
use serde_json::json; use serde_json::json;
@@ -45,6 +45,7 @@ impl Default for EmbedOptions {
static DEFAULT_DC_COL: u32 = 5793266; static DEFAULT_DC_COL: u32 = 5793266;
static REMOVED_DC_COL: u32 = 16716032; static REMOVED_DC_COL: u32 = 16716032;
pub static MANDATORY_MSG: &str = "Mandatory response, please ignore.";
fn none_to_empty(string: Option<String>) -> String { fn none_to_empty(string: Option<String>) -> String {
@@ -76,6 +77,20 @@ pub async fn send_msg(
} }
pub async fn http_send_msg(
http: &Http,
c_id: ChannelId,
t: String
) -> Option<Message>
{
let r = CreateMessage::new().content(t);
let msg = c_id.send_message(http, r).await;
return msg.ok();
}
pub async fn send_embed( pub async fn send_embed(
ctx: Context<'_>, ctx: Context<'_>,
options: EmbedOptions, options: EmbedOptions,
@@ -103,6 +118,21 @@ pub async fn send_embed(
} }
pub async fn http_send_embed(
http: &Http,
c_id: ChannelId,
options: EmbedOptions
) -> Option<Message>
{
let embed = embed_from_options(options.clone());
let r = CreateMessage::new().embeds(vec![embed]);
let msg = c_id.send_message(http, r).await;
return msg.ok();
}
pub fn embed_from_options(options: EmbedOptions) -> CreateEmbed { pub fn embed_from_options(options: EmbedOptions) -> CreateEmbed {
let mut author: Option<CreateEmbedAuthor> = None; let mut author: Option<CreateEmbedAuthor> = None;
if let Some(o_author) = options.author { if let Some(o_author) = options.author {
@@ -123,7 +153,7 @@ pub fn embed_from_options(options: EmbedOptions) -> CreateEmbed {
} }
pub async fn edit_msg( pub async fn edit_reply(
ctx: Context<'_>, ctx: Context<'_>,
msg: ReplyHandle<'_>, msg: ReplyHandle<'_>,
new_text: String new_text: String
@@ -137,6 +167,15 @@ pub async fn edit_msg(
} }
pub async fn http_edit_msg(
http: &Http,
mut msg: Message,
new_msg: EditMessage
) {
let _ = msg.edit(http, new_msg).await;
}
pub async fn send_dm(msg: String, args: Args) { pub async fn send_dm(msg: String, args: Args) {
let uid = env::var("ASSISTANT_DM_USER").expect("Missing ASSISTANT_DM_USER env var!").parse::<u64>().unwrap(); let uid = env::var("ASSISTANT_DM_USER").expect("Missing ASSISTANT_DM_USER env var!").parse::<u64>().unwrap();
let user = UserId::new(uid); let user = UserId::new(uid);
+3 -3
View File
@@ -7,7 +7,7 @@ import data
import posts import posts
BOT_ACTION_POSTFIX = "\n\n^(I am not an AI, I am just a bot. This action was preformed automatically by the way.)" BOT_ACTION_POSTFIX = "\n\n^(I am not an AI, I am just a bot. This action was performed automatically by the way.)"
async def make_cmd(cmd: str, bot: botPy.Bot) -> str: async def make_cmd(cmd: str, bot: botPy.Bot) -> str:
@@ -55,14 +55,14 @@ async def bk_week_add(mention: models.Comment, bot: botPy.Bot):
r = "" r = ""
bd = bot.data[data.BK_WEEKLY] bd = bot.data[data.BK_WEEKLY]
# TODO: ask if the messages should be changed
if short_url not in bd: if short_url not in bd:
posts.add_post_url(bot, short_url) posts.add_post_url(bot, short_url)
r = "Successfully added this post to the data!" r = "Successfully added this post to the data!"
if short_url in bd and is_mod: if short_url in bd and is_mod:
if "removed" in bd[short_url]: if "removed" in bd[short_url]:
r = "(Mod action) Successfully un-removed this post from the data! Glad to see you back!" r = "(Mod action) Successfully un-removed this post from the data!"
else: else:
r = "(Mod action) Successfully added this post to the data!" r = "(Mod action) Successfully added this post to the data!"