made bot add new posts to channel
This commit is contained in:
+90
-45
@@ -1,11 +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::{messages, rs_println, websocket, Context, Error, BK_WEEK};
|
||||||
use crate::messages::{edit_msg, send_embed, send_msg, EmbedOptions};
|
use crate::messages::{edit_msg, send_embed, send_msg};
|
||||||
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, GetMessages, Message, Timestamp};
|
use poise::serenity_prelude::{ChannelId, GetMessages, Message};
|
||||||
|
use poise::ReplyHandle;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
|
|
||||||
@@ -96,29 +97,7 @@ async fn get_post_from_data(ctx: Context<'_>, reddit_data: &Value, url: &str) ->
|
|||||||
|
|
||||||
|
|
||||||
async fn send_embed_for_post(ctx: Context<'_>, post: Value, url: &str) -> Result<(), Error> {
|
async fn send_embed_for_post(ctx: Context<'_>, post: Value, url: &str) -> Result<(), Error> {
|
||||||
let embed_options = EmbedOptions {
|
send_embed(ctx, messages::embed_post(&post, url, true), true).await;
|
||||||
desc: format!(
|
|
||||||
r#"**Spoilers and vote length anonymizer for fair review!**
|
|
||||||
Upvotes: ||`{:>6}`||
|
|
||||||
URL: ||<{}>||
|
|
||||||
Added by human: {}
|
|
||||||
Added by bot: {}
|
|
||||||
Approved by human: {}
|
|
||||||
Approved by bot: `[not implemented]`"#,
|
|
||||||
post["post_data"]["upvotes"].as_i64().unwrap(),
|
|
||||||
url,
|
|
||||||
if post["added"] ["by_human"].as_bool().unwrap() { "✅" } else { "❌" },
|
|
||||||
if post["added"] ["by_bot"].as_bool().unwrap() { "✅" } else { "❌" },
|
|
||||||
if post["approved"]["by_human"].as_bool().unwrap() { "✅" } else { "❌" }
|
|
||||||
).trim().to_string(),
|
|
||||||
title: Some(post["post_data"]["title"].as_str().unwrap().to_string()),
|
|
||||||
url: Some(url.to_string()),
|
|
||||||
ts: Some(Timestamp::from_unix_timestamp(post["post_data"]["date_unix"].as_i64().unwrap()).unwrap()),
|
|
||||||
empheral: true,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
send_embed(ctx, embed_options, true).await;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,6 +269,7 @@ async fn approve_cmd(ctx: Context<'_>, url: &str, reddit_data: &Value, approve:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, guild_only)]
|
#[poise::command(slash_command, prefix_command, guild_only)]
|
||||||
/// Opposite effects of `/bk_week_approve`.
|
/// Opposite effects of `/bk_week_approve`.
|
||||||
pub async fn bk_week_disapprove(
|
pub async fn bk_week_disapprove(
|
||||||
@@ -306,6 +286,8 @@ pub async fn bk_week_disapprove(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, default_member_permissions = "ADMINISTRATOR", guild_only)]
|
#[poise::command(slash_command, prefix_command, default_member_permissions = "ADMINISTRATOR", guild_only)]
|
||||||
/// Sets the channel where the bot will dump all log info. It's recommended to only run this once.
|
/// Sets the channel where the bot will dump all log info. It's recommended to only run this once.
|
||||||
pub async fn bk_week_bind(
|
pub async fn bk_week_bind(
|
||||||
@@ -331,6 +313,8 @@ async fn send_server_not_in_data_msg(ctx: Context<'_>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, default_member_permissions = "ADMINISTRATOR", guild_only)]
|
#[poise::command(slash_command, prefix_command, default_member_permissions = "ADMINISTRATOR", guild_only)]
|
||||||
/// Updates all logs
|
/// Updates all logs
|
||||||
pub async fn bk_week_update(
|
pub async fn bk_week_update(
|
||||||
@@ -338,9 +322,66 @@ 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 progress = send_msg(ctx, p_text.clone(), true, true).await;
|
||||||
|
|
||||||
|
send_cmd_json("add_new_posts", json!([])).await;
|
||||||
|
let r_data = get_reddit_data(ctx).await.unwrap();
|
||||||
|
|
||||||
|
let c_id = get_c_id(ctx).await.unwrap_or_else(|| 0);
|
||||||
|
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), format!("Done!\nReading messages in <#{}>...", c_id)).await;
|
||||||
|
|
||||||
|
if c_id == 0 {
|
||||||
|
send_msg(ctx, "Could not find bk_week_channel in data!\nHint: Run `/bk_week_bind` in a (preferably read-only) channel.".to_string(), true, true).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let msgs = read_msgs(ctx, c_id).await;
|
||||||
|
|
||||||
|
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "Done!\nParsing messages to JSON...".to_string()).await;
|
||||||
|
let msgs_json = msgs_to_json(ctx, msgs, &r_data).await;
|
||||||
|
|
||||||
|
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "Done!\nAdding new posts...".to_string()).await;
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: parse to JSON
|
||||||
|
// json should be {"added": [], "updated": [], "removed": []}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: add new posts to channel
|
||||||
|
let weekly_art = r_data["bk_weekly_art_posts"].as_object().unwrap();
|
||||||
|
|
||||||
|
for url in weekly_art.keys() {
|
||||||
|
if msgs_json.get(url).is_some() { continue; }
|
||||||
|
if weekly_art[url].get("removed").is_some() { continue; }
|
||||||
|
|
||||||
|
send_embed(ctx, messages::embed_post(&weekly_art[url], url, false), false).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: edit outdated posts
|
||||||
|
// TODO: remove removed posts
|
||||||
|
|
||||||
|
/* MSG FORMAT:
|
||||||
|
{json as spoiler}
|
||||||
|
{embed}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn update_progress(ctx: Context<'_>, p: ReplyHandle<'_>, t: String, a_t: String) -> String {
|
||||||
|
let p_text = format!("{} {}", t, a_t);
|
||||||
|
edit_msg(ctx, p, p_text.clone()).await;
|
||||||
|
return p_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn get_c_id(ctx: Context<'_>) -> Option<u64> {
|
||||||
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 Ok(());
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let d_lock = ctx.data().discord_data.lock().await;
|
let d_lock = ctx.data().discord_data.lock().await;
|
||||||
@@ -350,16 +391,13 @@ pub async fn bk_week_update(
|
|||||||
[ctx.guild_id().unwrap().to_string()]
|
[ctx.guild_id().unwrap().to_string()]
|
||||||
["bk_week_channel"].as_u64().unwrap();
|
["bk_week_channel"].as_u64().unwrap();
|
||||||
|
|
||||||
if c_id == 0 {
|
return Some(c_id);
|
||||||
send_msg(ctx, "Could not find bk_week_channel in data!\nHint: Run `/bk_week_bind` in a (preferably read-only) channel.".to_string(), true, true).await;
|
}
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
async fn read_msgs(ctx: Context<'_>, c_id: u64) -> Vec<Message> {
|
||||||
let c = ChannelId::new(c_id);
|
let c = ChannelId::new(c_id);
|
||||||
|
|
||||||
let mut p_text = format!("Reading messages in <#{}>...", c_id);
|
|
||||||
let progress = send_msg(ctx, p_text.clone(), true, true).await;
|
|
||||||
|
|
||||||
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.messages(ctx.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 == ctx.framework().bot_id).collect();
|
||||||
@@ -384,15 +422,22 @@ pub async fn bk_week_update(
|
|||||||
msgs.extend(filtered_msgs);
|
msgs.extend(filtered_msgs);
|
||||||
}
|
}
|
||||||
|
|
||||||
p_text = p_text.as_str().to_owned() + " Done!";
|
return msgs;
|
||||||
edit_msg(ctx, progress.unwrap(), p_text).await;
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO: parse to JSON
|
async fn msgs_to_json(ctx: Context<'_>, msgs: Vec<Message>, reddit_data: &Value) -> Value {
|
||||||
// TODO: add new posts to channel
|
let mut msgs_json = json!({"no_change": [], "updated": [], "removed": []});
|
||||||
// TODO: edit outdated posts
|
|
||||||
// TODO: remove removed posts
|
for msg in msgs {
|
||||||
|
let msg_json = serde_json::from_str(&msg.content);
|
||||||
|
if msg_json.is_ok() {
|
||||||
return Ok(());
|
let u_json: Value = msg_json.unwrap();
|
||||||
|
println!("{:?}", u_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
else { continue }
|
||||||
|
}
|
||||||
|
|
||||||
|
return msgs_json;
|
||||||
}
|
}
|
||||||
+7
-5
@@ -73,7 +73,8 @@ pub async fn embed(
|
|||||||
#[description = "A URL the title is bound to."] url: Option<String>,
|
#[description = "A URL the title is bound to."] url: Option<String>,
|
||||||
#[description = "Timestamp at bottom (best to leave empty)."] timestamp: Option<Timestamp>,
|
#[description = "Timestamp at bottom (best to leave empty)."] timestamp: Option<Timestamp>,
|
||||||
#[description = "Empheral (only visible to you)."] empheral: Option<bool>,
|
#[description = "Empheral (only visible to you)."] empheral: Option<bool>,
|
||||||
#[description = "Shows \"used {Command}\" reply text."] reply: Option<bool>
|
#[description = "Shows \"used {Command}\" reply text."] reply: Option<bool>,
|
||||||
|
#[description = "Text that appears above and outside of the embed"] message: Option<String>
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
let reply_unwrap = reply.unwrap_or_else(|| false);
|
let reply_unwrap = reply.unwrap_or_else(|| false);
|
||||||
@@ -81,12 +82,13 @@ pub async fn embed(
|
|||||||
send_embed(
|
send_embed(
|
||||||
ctx,
|
ctx,
|
||||||
EmbedOptions {
|
EmbedOptions {
|
||||||
desc: description,
|
desc: description.replace("\\n", "\n"),
|
||||||
title,
|
title: Some(title.unwrap().replace("\\n", "\n")),
|
||||||
col: color,
|
col: color,
|
||||||
url,
|
url,
|
||||||
ts: timestamp,
|
ts: timestamp,
|
||||||
empheral: empheral.unwrap_or_else(|| false)
|
empheral: empheral.unwrap_or_else(|| false),
|
||||||
|
message
|
||||||
},
|
},
|
||||||
reply_unwrap
|
reply_unwrap
|
||||||
).await;
|
).await;
|
||||||
@@ -111,7 +113,7 @@ pub async fn send(
|
|||||||
#[description = "The message to send (NO EMPHERAL)"] msg: String
|
#[description = "The message to send (NO EMPHERAL)"] msg: String
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
send_msg(ctx, msg, 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 success response, please ignore.".to_string(), true, true).await;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|||||||
+51
-3
@@ -1,5 +1,6 @@
|
|||||||
use crate::Context;
|
use crate::Context;
|
||||||
|
|
||||||
|
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, Timestamp};
|
use poise::serenity_prelude::{Color, CreateEmbed, Timestamp};
|
||||||
|
|
||||||
@@ -10,7 +11,8 @@ pub struct EmbedOptions {
|
|||||||
pub col: Option<u32>,
|
pub col: Option<u32>,
|
||||||
pub url: Option<String>,
|
pub url: Option<String>,
|
||||||
pub ts: Option<Timestamp>,
|
pub ts: Option<Timestamp>,
|
||||||
pub empheral: bool
|
pub empheral: bool,
|
||||||
|
pub message: Option<String>
|
||||||
}
|
}
|
||||||
impl Default for EmbedOptions {
|
impl Default for EmbedOptions {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
@@ -20,12 +22,16 @@ impl Default for EmbedOptions {
|
|||||||
col: None,
|
col: None,
|
||||||
url: None,
|
url: None,
|
||||||
ts: None,
|
ts: None,
|
||||||
empheral: false
|
empheral: false,
|
||||||
|
message: None
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static DEFAULT_DC_COL: u32 = 5793266;
|
||||||
|
|
||||||
|
|
||||||
fn none_to_empty(string: Option<String>) -> String {
|
fn none_to_empty(string: Option<String>) -> String {
|
||||||
return string.unwrap_or_else(|| "".to_string());
|
return string.unwrap_or_else(|| "".to_string());
|
||||||
}
|
}
|
||||||
@@ -64,7 +70,7 @@ pub async fn send_embed(
|
|||||||
let mut embed = CreateEmbed::new()
|
let mut embed = CreateEmbed::new()
|
||||||
.title (none_to_empty(options.title))
|
.title (none_to_empty(options.title))
|
||||||
.description(options.desc)
|
.description(options.desc)
|
||||||
.colour (Color::new(options.col.unwrap_or_else(|| 5793266)))
|
.colour (Color::new(options.col.unwrap_or_else(|| DEFAULT_DC_COL)))
|
||||||
.url (none_to_empty(options.url));
|
.url (none_to_empty(options.url));
|
||||||
|
|
||||||
if options.ts.is_some() { embed = embed.timestamp(options.ts.unwrap()); }
|
if options.ts.is_some() { embed = embed.timestamp(options.ts.unwrap()); }
|
||||||
@@ -72,6 +78,7 @@ pub async fn send_embed(
|
|||||||
if reply {
|
if reply {
|
||||||
let r = CreateReply {
|
let r = CreateReply {
|
||||||
embeds: vec![embed],
|
embeds: vec![embed],
|
||||||
|
content: options.message,
|
||||||
ephemeral: Some(options.empheral),
|
ephemeral: Some(options.empheral),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@@ -99,3 +106,44 @@ pub async fn edit_msg(
|
|||||||
|
|
||||||
let _ = msg.edit(ctx, r).await;
|
let _ = msg.edit(ctx, r).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub fn embed_post(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions {
|
||||||
|
let desc_str = format!(
|
||||||
|
r#"Sorted by what I think will be most important
|
||||||
|
Spoilers and vote length anonymizer for fair review!
|
||||||
|
## Post Data:
|
||||||
|
**Media type:** `{}`
|
||||||
|
**Upvotes:** ||`{:>6}`||
|
||||||
|
**URL:** ||<{}>||
|
||||||
|
**Media URLS:**
|
||||||
|
{}
|
||||||
|
|
||||||
|
## Listing Data:
|
||||||
|
**Added by:** `{{ human: {}, bot: {} }}`
|
||||||
|
**Approved by:** `{{ human: {}, bot: [not implemented] }}`"#,
|
||||||
|
post_data["post_data"]["media_type"].as_str().unwrap(),
|
||||||
|
post_data["post_data"]["upvotes"].as_i64().unwrap(),
|
||||||
|
url,
|
||||||
|
post_data["post_data"]["media_urls"].as_array().unwrap().iter().map(|s| format!("* ||<{}>||", s.as_str().unwrap())).collect::<Vec<_>>().join("\n"),
|
||||||
|
if post_data["added"] ["by_human"].as_bool().unwrap() { "✅" } else { "❌" },
|
||||||
|
if post_data["added"] ["by_bot"].as_bool().unwrap() { "✅" } else { "❌" },
|
||||||
|
if post_data["approved"]["by_human"].as_bool().unwrap() { "✅" } else { "❌" }
|
||||||
|
);
|
||||||
|
|
||||||
|
let trimmed = desc_str
|
||||||
|
.lines()
|
||||||
|
.map(|line| line.trim())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n");
|
||||||
|
|
||||||
|
return EmbedOptions {
|
||||||
|
title: Some(post_data["post_data"]["title"].as_str().unwrap().to_string()),
|
||||||
|
desc: trimmed,
|
||||||
|
col: Some(DEFAULT_DC_COL),
|
||||||
|
url: Some(url.to_string()),
|
||||||
|
ts: Some(Timestamp::from_unix_timestamp(post_data["post_data"]["date_unix"].as_i64().unwrap()).unwrap()),
|
||||||
|
message: Some(format!("||`{{\"{}\":{}}}`||", url, serde_json::to_string(post_data).unwrap())),
|
||||||
|
empheral
|
||||||
|
};
|
||||||
|
}
|
||||||
+2
-1
@@ -6,7 +6,7 @@ import bot as botPy
|
|||||||
from macros import *
|
from macros import *
|
||||||
|
|
||||||
|
|
||||||
async def add_new_posts(bot: botPy.Bot):
|
async def add_new_posts(bot: botPy.Bot) -> bool:
|
||||||
check_emoji = emoji.emojize(":check_mark_button:")
|
check_emoji = emoji.emojize(":check_mark_button:")
|
||||||
cross_emoji = emoji.emojize(":cross_mark:")
|
cross_emoji = emoji.emojize(":cross_mark:")
|
||||||
|
|
||||||
@@ -49,6 +49,7 @@ async def add_new_posts(bot: botPy.Bot):
|
|||||||
f"and {not_added} weren't added because they are removed or already existed")
|
f"and {not_added} weren't added because they are removed or already existed")
|
||||||
|
|
||||||
data.write_data(bot)
|
data.write_data(bot)
|
||||||
|
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_name: str) -> list[models.Submission]:
|
||||||
|
|||||||
@@ -64,6 +64,7 @@ async def json_to_func(v: dict, bot: botPy.Bot) -> dict:
|
|||||||
|
|
||||||
match v["value"]:
|
match v["value"]:
|
||||||
case "update_data_file": result = result_json(data.write_data(bot))
|
case "update_data_file": result = result_json(data.write_data(bot))
|
||||||
|
case "add_new_posts": result = result_json(await posts.add_new_posts(bot))
|
||||||
case "add_post_url": result = result_json(await posts.add_post_url(bot, *v["args"]))
|
case "add_post_url": result = result_json(await posts.add_post_url(bot, *v["args"]))
|
||||||
case "remove_post_url": result = result_json(data.remove_post(bot, *v["args"]))
|
case "remove_post_url": result = result_json(data.remove_post(bot, *v["args"]))
|
||||||
case "set_approve_post": result = result_json(data.set_approve_post(bot, *v["args"]))
|
case "set_approve_post": result = result_json(data.set_approve_post(bot, *v["args"]))
|
||||||
|
|||||||
Reference in New Issue
Block a user