buh
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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]`~~ -->
|
||||||
|
|||||||
+113
-75
@@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "✅\nRemoving removed posts...".to_string()).await;
|
// Removing removed posts
|
||||||
for (url, msg_id) in msgs_json["removed"].as_object().unwrap() {
|
p_text = update_progress(http, progress.clone(), p_text.clone(), "✅\nRemoving removed posts...".to_string()).await;
|
||||||
let mut msg = ctx.http().get_message(ctx.channel_id(), MessageId::new(msg_id.as_u64().unwrap())).await.unwrap();
|
remove_posts(http, c_id, weekly_art, &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;
|
|
||||||
}
|
|
||||||
|
|
||||||
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "✅\nRemoving duplicate posts...".to_string()).await;
|
// Removing duplicate posts
|
||||||
for (_url, msgs) in msgs_json["duplicates"].as_object().unwrap() {
|
update_progress(http, progress.clone(), p_text.clone(), "✅\nRemoving duplicate posts...".to_string()).await;
|
||||||
for msg_id in msgs.as_array().unwrap() {
|
remove_dupes(http, c_id, &msgs_json).await;
|
||||||
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;
|
// Done
|
||||||
|
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(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
@@ -600,4 +638,4 @@ pub async fn bk_week_vote(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-5
@@ -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 {
|
||||||
|
|||||||
+13
-8
@@ -55,10 +55,11 @@ 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();
|
||||||
|
|
||||||
file.write_all(json_str.as_bytes()).unwrap();
|
file.write_all(json_str.as_bytes()).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
@@ -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();
|
||||||
@@ -236,8 +243,4 @@ async fn run_schedules(schedules: Vec<(Duration, fn() -> Pin<Box<dyn Future<Outp
|
|||||||
async fn read_reddit_inbox() {
|
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
@@ -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
@@ -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!"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user