added voting system, bug fixes, and a ton more
This commit is contained in:
@@ -5,11 +5,13 @@
|
|||||||
<!-- - [x] ~~Scrape the data~~ -->
|
<!-- - [x] ~~Scrape the data~~ -->
|
||||||
<!-- - [x] ~~Put it in a JSON~~ -->
|
<!-- - [x] ~~Put it in a JSON~~ -->
|
||||||
<!-- - [x] ~~Multithread so it can run both Discord and Reddit bot!!!~~ -->¨
|
<!-- - [x] ~~Multithread so it can run both Discord and Reddit bot!!!~~ -->¨
|
||||||
- [ ] Security that only allows bk mods to run these commands
|
<!-- - [x] Security that only allows bk mods to run these commands. -->
|
||||||
|
<!-- - [x] Some kind of voting system. -->
|
||||||
- [ ] Allow updating the data autonomously and via manual commands.
|
- [ ] Allow updating the data autonomously and via manual commands.
|
||||||
- [ ] 30-minute schedule
|
- [ ] 30-minute schedule when bot adds posts
|
||||||
- [ ] Manually add posts
|
- [ ] Manually add posts
|
||||||
- [ ] via `u/[bot] add`
|
- [ ] via `u/[bot] add`
|
||||||
|
- [ ] 5 minute schedule when user adds post
|
||||||
<!-- - [x] ~~via `/bk_week_add [url]`~~ -->
|
<!-- - [x] ~~via `/bk_week_add [url]`~~ -->
|
||||||
<!-- - [x] ~~Manually remove posts via `/bk_week_remove [url]`~~ -->
|
<!-- - [x] ~~Manually remove posts via `/bk_week_remove [url]`~~ -->
|
||||||
<!-- - [x] ~~Manually approve posts via `/bk_week_approve [url]`~~ -->
|
<!-- - [x] ~~Manually approve posts via `/bk_week_approve [url]`~~ -->
|
||||||
@@ -18,7 +20,7 @@
|
|||||||
- [ ] Automatically remove posts older than 7 days from JSON
|
- [ ] Automatically remove posts older than 7 days from JSON
|
||||||
- [x] ~~Function~~
|
- [x] ~~Function~~
|
||||||
- [ ] Automate
|
- [ ] Automate
|
||||||
- [ ] Automatically approve posts that dont get caught by reverse image search (ris)
|
- [ ] Automatically approve posts that don't get caught by reverse image search (ris)
|
||||||
<!-- - [x] Log all posts in a Discord thread -->
|
<!-- - [x] Log all posts in a Discord thread -->
|
||||||
<!-- - [x] ~~`/bk_week_bind` to bind a channel for bk_week logs~~ -->
|
<!-- - [x] ~~`/bk_week_bind` to bind a channel for bk_week logs~~ -->
|
||||||
<!-- - [x] Add post if it exists in data but not in channel -->
|
<!-- - [x] Add post if it exists in data but not in channel -->
|
||||||
@@ -29,9 +31,9 @@
|
|||||||
|
|
||||||
### Medium priority:
|
### Medium priority:
|
||||||
<!-- - [x] ~~JSON -> Rules list~~ -->
|
<!-- - [x] ~~JSON -> Rules list~~ -->
|
||||||
- [ ] View single rule (/rule {rulename})
|
- [ ] View single rule (/rule {rule_name})
|
||||||
- [ ] Postfix calculator
|
- [ ] Postfix calculator
|
||||||
- [ ] Postfic generator
|
- [ ] Postfix generator
|
||||||
- [ ] JSON -> BPS class init
|
- [ ] JSON -> BPS class init
|
||||||
- [ ] BPS args -> JSON
|
- [ ] BPS args -> JSON
|
||||||
- [ ] Random tip (from ByteDice.net/data/loadingScreenTips.json)
|
- [ ] Random tip (from ByteDice.net/data/loadingScreenTips.json)
|
||||||
@@ -44,7 +46,7 @@
|
|||||||
- [ ] Weekly coding competition
|
- [ ] Weekly coding competition
|
||||||
* Same as particle of the week but with coding
|
* Same as particle of the week but with coding
|
||||||
- [ ] Content update sender
|
- [ ] Content update sender
|
||||||
* Automatically sends sneek peeks (like commit history or manual) of projects when theyre updated
|
* Automatically sends sneak peeks (like commit history or manual) of projects when they're updated
|
||||||
- [ ] Language TLDR command
|
- [ ] Language TLDR command
|
||||||
* Shows a TLDR with pros/cons on a programming language
|
* Shows a TLDR with pros/cons on a programming language
|
||||||
- [ ] PowerPlate info viewer
|
- [ ] PowerPlate info viewer
|
||||||
|
|||||||
+9
-7
@@ -1,16 +1,18 @@
|
|||||||
# Discord Commands
|
# Discord Commands
|
||||||
## `/bk_week_add [url] [approve]`
|
## `/bk_week_add [url] <approve>`
|
||||||
Adds a URL to the list of posts. This is done automatically by the bot for certain posts.
|
Adds a URL to the list of posts. This is done automatically by the bot for certain posts.
|
||||||
- **`[approve]`**: `true` or `false`, determines whether to pre-approve the post.
|
- **`<approve>`**: (OPTIONAL) `true` or `false`, determines whether to pre-approve the post.
|
||||||
## `/bk_week_remove [url]`
|
## `/bk_week_remove [url]`
|
||||||
Removes an existing URL from the list of posts.
|
Removes an existing URL from the list of posts.
|
||||||
## `/bk_week_approve [url]`
|
## `/bk_week_approve [url] <disapprove>`
|
||||||
Flags the post as **human_approved**, confirming that the artwork is original.
|
Flags the post as **human_approved**, confirming that the artwork is original.
|
||||||
## `/bk_week_disapprove [url]`
|
- **`<disapprove>`**: (OPTIONAL) `true` or `false`, set to `true` if you want to undo an approval.
|
||||||
Reverses the effect of `/bk_week_approve`.
|
|
||||||
## `/bk_week_update`
|
## `/bk_week_update`
|
||||||
Updates all data in the binded Discord channel. It's reccommended to run this rarely.
|
Updates all data in the bound Discord channel. It's recommended to run this rarely.
|
||||||
## `/bk_week_bind`
|
## `/bk_week_vote [url] <remove_vote>`
|
||||||
|
Adds a vote to a post. The intended use for votes is for a "moderator picks" and a "community picks" section of the weekly art.
|
||||||
|
You can vote on as many posts as you want, but only once per post.
|
||||||
|
## `/bk_admin_bind`
|
||||||
Binds the current channel as the channel where the bk_week data is sent and updated in. No binding means the only way to view the data is using `/bk_week_get`.
|
Binds the current channel as the channel where the bk_week data is sent and updated in. No binding means the only way to view the data is using `/bk_week_get`.
|
||||||
### **Examples**
|
### **Examples**
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -4,6 +4,9 @@ To execute a command on the Reddit bot, include `u/ByteDiceAssistant [args]` in
|
|||||||
## `bk_week_add`
|
## `bk_week_add`
|
||||||
Adds the post to the list of posts.
|
Adds the post to the list of posts.
|
||||||
- **Only moderators of a subreddit or the OP (Original Poster) can use this command.**
|
- **Only moderators of a subreddit or the OP (Original Poster) can use this command.**
|
||||||
|
## `bk_week_vote`
|
||||||
|
Adds a vote to the post. (see `/bk_week_vote` in the Discord help).
|
||||||
|
- **Anyone can use this command.**
|
||||||
### **Examples**
|
### **Examples**
|
||||||
```
|
```
|
||||||
"u/ByteDiceAssistant bk_week_add"
|
"u/ByteDiceAssistant bk_week_add"
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"bk1": {
|
||||||
|
"discord": [
|
||||||
|
697149665166229614,
|
||||||
|
526842473062989864,
|
||||||
|
1171015493537247273,
|
||||||
|
1156779840956010496,
|
||||||
|
1021944396473716847,
|
||||||
|
1085622021024653362,
|
||||||
|
1223480842525872148,
|
||||||
|
1155349278655520858
|
||||||
|
],
|
||||||
|
"reddit": [
|
||||||
|
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"bk2": {
|
||||||
|
"discord": [
|
||||||
|
1004132854227292272,
|
||||||
|
1031352334745354282,
|
||||||
|
1173039143245332520,
|
||||||
|
1281040971710201857,
|
||||||
|
772049174672703528
|
||||||
|
],
|
||||||
|
"reddit": [
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
{
|
{
|
||||||
"file_created_correctly": true,
|
|
||||||
"bk_weekly_art_posts": {
|
"bk_weekly_art_posts": {
|
||||||
"EXAMPLE VALUE": {
|
"EXAMPLE VALUE": {
|
||||||
"post_data": {
|
"post_data": {
|
||||||
@@ -9,7 +8,11 @@
|
|||||||
"media_type": null,
|
"media_type": null,
|
||||||
"media_urls": []
|
"media_urls": []
|
||||||
},
|
},
|
||||||
"nominated_by_human": true,
|
"votes": {
|
||||||
|
"voters_re": ["bytedice"],
|
||||||
|
"voters_dc": [0],
|
||||||
|
"mod_voters": [0]
|
||||||
|
},
|
||||||
"added": {
|
"added": {
|
||||||
"by_human": false,
|
"by_human": false,
|
||||||
"by_bot": true
|
"by_bot": true
|
||||||
@@ -21,7 +24,8 @@
|
|||||||
},
|
},
|
||||||
"EXAMPLE VALUE DELETED": {
|
"EXAMPLE VALUE DELETED": {
|
||||||
"removed": true,
|
"removed": true,
|
||||||
"removed_by": "ME!!!!"
|
"removed_by": "ME!!!!",
|
||||||
|
"remove_reason": "i HATED that post >:("
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+107
-34
@@ -17,6 +17,20 @@ enum HelpOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn is_bk_mod(mod_list: Value, uid: u64) -> bool {
|
||||||
|
let obj = mod_list.as_object().unwrap();
|
||||||
|
let bk1_arr = obj["bk1"]["discord"].as_array().unwrap();
|
||||||
|
let bk2_arr = obj["bk2"]["discord"].as_array().unwrap();
|
||||||
|
|
||||||
|
return bk1_arr.contains(&json!(uid)) || bk2_arr.contains(&json!(uid));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn not_bk_mod_msg(ctx: Context<'_>) {
|
||||||
|
send_msg(ctx, "Permission denied: You are not a moderator of r/boykisser or r/boykisser2".to_string(), true, true).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
slash_command,
|
slash_command,
|
||||||
prefix_command
|
prefix_command
|
||||||
@@ -48,11 +62,11 @@ pub async fn bk_week_help(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, guild_only)]
|
#[poise::command(slash_command, prefix_command)]
|
||||||
/// Retrieves the data of a single post just for you. The data has to be within the database to work.
|
/// Retrieves the data of a single post just for you. The data has to be within the database to work.
|
||||||
pub async fn bk_week_get(
|
pub async fn bk_week_get(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[description = "The post URL"] url: String
|
#[description = "The post URL."] url: String
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
data::update_re_data(ctx.data()).await;
|
data::update_re_data(ctx.data()).await;
|
||||||
@@ -68,10 +82,10 @@ pub async fn bk_week_get(
|
|||||||
|
|
||||||
async fn get_reddit_data(ctx: Context<'_>) -> Result<Value, Error> {
|
async fn get_reddit_data(ctx: Context<'_>) -> Result<Value, Error> {
|
||||||
let data_lock = ctx.data().reddit_data.lock().await;
|
let data_lock = ctx.data().reddit_data.lock().await;
|
||||||
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()),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -146,14 +160,19 @@ async fn send_data_corrupted_message(ctx: Context<'_>, url: &str) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, guild_only)]
|
#[poise::command(slash_command, prefix_command)]
|
||||||
/// Fetches a post from Reddit and adds it to the database.
|
/// Fetches a post from Reddit and adds it to the database.
|
||||||
pub async fn bk_week_add(
|
pub async fn bk_week_add(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[description = "The post URL"] url: String,
|
#[description = "The post URL."] url: String,
|
||||||
#[description = "Wether to approve it after adding it"] approve: Option<bool>
|
#[description = "Wether to approve it after adding it"] approve: Option<bool>
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
|
if !is_bk_mod(ctx.data().bk_mods_json.clone(), ctx.author().id.get()) {
|
||||||
|
not_bk_mod_msg(ctx).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
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).await.unwrap();
|
||||||
|
|
||||||
@@ -206,15 +225,21 @@ async fn send_updated_msg(ctx: Context<'_>, url: &str) {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, guild_only)]
|
#[poise::command(slash_command, prefix_command)]
|
||||||
/// Removes a post from the database. It will show who last removed it.
|
/// Removes a post from the database. It will show who last removed it.
|
||||||
pub async fn bk_week_remove(
|
pub async fn bk_week_remove(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[description = "The post URL"] url: String
|
#[description = "The post URL."] url: String,
|
||||||
|
#[description = "The reason of the removal."] reason: Option<String>
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
|
if !is_bk_mod(ctx.data().bk_mods_json.clone(), ctx.author().id.get()) {
|
||||||
|
not_bk_mod_msg(ctx).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let auth = &ctx.author().name;
|
let auth = &ctx.author().name;
|
||||||
let r = send_cmd_json("remove_post_url", json!([&url, &auth])).await.unwrap();
|
let r = send_cmd_json("remove_post_url", json!([&url, &auth, &reason])).await.unwrap();
|
||||||
|
|
||||||
if r["value"].as_bool().unwrap() {
|
if r["value"].as_bool().unwrap() {
|
||||||
send_msg(
|
send_msg(
|
||||||
@@ -234,17 +259,23 @@ pub async fn bk_week_remove(
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, guild_only)]
|
#[poise::command(slash_command, prefix_command)]
|
||||||
/// Approves a post in the database. Approving posts tells the bot that it's original.
|
/// Approves a post in the database. Approving posts tells the bot that it's original.
|
||||||
pub async fn bk_week_approve(
|
pub async fn bk_week_approve(
|
||||||
ctx: Context<'_>,
|
ctx: Context<'_>,
|
||||||
#[description = "The post URL"] url: String
|
#[description = "The post URL."] url: String,
|
||||||
|
#[description = "Wether to approve or disapprove the post"] disapprove: Option<bool>
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
|
if !is_bk_mod(ctx.data().bk_mods_json.clone(), ctx.author().id.get()) {
|
||||||
|
not_bk_mod_msg(ctx).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
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).await.unwrap();
|
||||||
|
|
||||||
approve_cmd(ctx, &url, &reddit_data, true).await;
|
approve_cmd(ctx, &url, &reddit_data, !disapprove.unwrap_or_else(|| false)).await;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -277,27 +308,9 @@ async fn approve_cmd(ctx: Context<'_>, url: &str, reddit_data: &Value, approve:
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(slash_command, prefix_command, guild_only)]
|
|
||||||
/// Opposite effects of `/bk_week_approve`.
|
|
||||||
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(());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#[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_admin_bind(
|
||||||
ctx: Context<'_>
|
ctx: Context<'_>
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
@@ -333,23 +346,23 @@ pub async fn bk_week_update(
|
|||||||
let progress = send_msg(ctx, p_text.clone(), true, true).await;
|
let progress = send_msg(ctx, p_text.clone(), true, true).await;
|
||||||
|
|
||||||
send_cmd_json("add_new_posts", json!([])).await;
|
send_cmd_json("add_new_posts", json!([])).await;
|
||||||
|
data::update_re_data(ctx.data()).await;
|
||||||
let r_data = get_reddit_data(ctx).await.unwrap();
|
let r_data = get_reddit_data(ctx).await.unwrap();
|
||||||
|
|
||||||
let c_id = get_c_id(ctx).await.unwrap_or_else(|| 0);
|
let c_id = get_c_id(ctx).await.unwrap_or_else(|| 0);
|
||||||
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), format!("✅\nReading messages in <#{}>...", c_id)).await;
|
|
||||||
|
|
||||||
if c_id == 0 {
|
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;
|
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 msgs = read_msgs(ctx, c_id).await;
|
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;
|
p_text = update_progress(ctx, progress.clone().unwrap(), 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;
|
p_text = update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "✅\nAdding new posts...".to_string()).await;
|
||||||
|
|
||||||
let weekly_art = r_data["bk_weekly_art_posts"].as_object().unwrap();
|
let weekly_art = r_data["bk_weekly_art_posts"].as_object().unwrap();
|
||||||
|
|
||||||
for url in weekly_art.keys() {
|
for url in weekly_art.keys() {
|
||||||
@@ -399,6 +412,7 @@ pub async fn bk_week_update(
|
|||||||
}
|
}
|
||||||
|
|
||||||
update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "✅\n## Done!".to_string()).await;
|
update_progress(ctx, progress.clone().unwrap(), p_text.clone(), "✅\n## Done!".to_string()).await;
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -458,6 +472,8 @@ async fn read_msgs(ctx: Context<'_>, c_id: u64) -> Vec<Message> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: all posts get updated for some reason (i think, debug print pls)
|
||||||
|
// TODO: also doesn't edit messages if they got removed
|
||||||
async fn msgs_to_json<'a>(msgs: Vec<Message>, reddit_data: &'a Value) -> Value {
|
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": {}});
|
||||||
|
|
||||||
@@ -509,6 +525,7 @@ async fn msgs_to_json<'a>(msgs: Vec<Message>, reddit_data: &'a Value) -> Value {
|
|||||||
if u_json["added"] != re_url["added"]
|
if u_json["added"] != re_url["added"]
|
||||||
|| u_json["approved"] != re_url["approved"]
|
|| u_json["approved"] != re_url["approved"]
|
||||||
|| u_json["post_data"]["upvotes"] != re_url["post_data"]["upvotes"]
|
|| u_json["post_data"]["upvotes"] != re_url["post_data"]["upvotes"]
|
||||||
|
|| u_json["votes"] != re_url["votes"]
|
||||||
{
|
{
|
||||||
u_json.as_object_mut().unwrap().insert("msg_id".to_string(), Value::String(msg.id.clone().to_string()));
|
u_json.as_object_mut().unwrap().insert("msg_id".to_string(), Value::String(msg.id.clone().to_string()));
|
||||||
|
|
||||||
@@ -526,3 +543,59 @@ async fn msgs_to_json<'a>(msgs: Vec<Message>, reddit_data: &'a Value) -> Value {
|
|||||||
|
|
||||||
return msgs_json;
|
return msgs_json;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[poise::command(slash_command, prefix_command)]
|
||||||
|
pub async fn bk_week_vote(
|
||||||
|
ctx: Context<'_>,
|
||||||
|
#[description = "The post URL."] url: String,
|
||||||
|
#[description = "Wether to undo your vote or not"] un_vote: Option<bool>
|
||||||
|
) -> Result<(), Error>
|
||||||
|
{
|
||||||
|
data::update_re_data(ctx.data()).await;
|
||||||
|
let uid = ctx.author().id.get();
|
||||||
|
let re_data = get_reddit_data(ctx).await.unwrap();
|
||||||
|
let post_data = re_data["bk_weekly_art_posts"].clone();
|
||||||
|
let unw_vote = un_vote.unwrap_or_else(|| false);
|
||||||
|
|
||||||
|
if post_data.get(&url).is_none() {
|
||||||
|
send_post_not_found_message(ctx, &url).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let url_data = &post_data[&url];
|
||||||
|
|
||||||
|
let is_mod = is_bk_mod(ctx.data().bk_mods_json.clone(), ctx.author().id.get());
|
||||||
|
let voters_dc = url_data["votes"]["voters_dc"].as_array().unwrap();
|
||||||
|
let mod_voters = url_data["votes"]["mod_voters"].as_array().unwrap();
|
||||||
|
let voters = if is_mod { mod_voters } else { voters_dc };
|
||||||
|
|
||||||
|
if voters.contains(&json!(uid)) && !unw_vote {
|
||||||
|
send_msg(ctx, "Couldn't cast a vote: You have already voted on this post!".to_string(), true, true).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
else if !voters.contains(&json!(uid)) && unw_vote {
|
||||||
|
send_msg(ctx, "Couldn't remove your vote: You haven't voted on this post yet!".to_string(), true, true).await;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
let r = send_cmd_json("set_vote_post", json!([url, uid, is_mod, true, unw_vote])).await.unwrap();
|
||||||
|
let unw_r = r["value"].as_bool().unwrap();
|
||||||
|
|
||||||
|
if unw_r && !unw_vote && is_mod {
|
||||||
|
send_msg(ctx, "Successfully voted (as moderator vote)!".to_string(), true, true).await;
|
||||||
|
}
|
||||||
|
else if unw_r && !unw_vote && !is_mod {
|
||||||
|
send_msg(ctx, "Successfully voted!".to_string(), true, true).await;
|
||||||
|
}
|
||||||
|
else if unw_r && unw_vote {
|
||||||
|
send_msg(ctx, "Successfully removed vote!".to_string(), true, true).await;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
send_msg(ctx, "Failed to vote/un-vote: Unknown internal error".to_string(), true, true).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
+8
-4
@@ -23,7 +23,6 @@ use serde_json;
|
|||||||
|
|
||||||
|
|
||||||
// TODO: bot command permissions
|
// TODO: bot command permissions
|
||||||
// TODO: bk_mod verification system
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Parser, Serialize, Clone)]
|
#[derive(Parser, Serialize, Clone)]
|
||||||
@@ -49,6 +48,7 @@ struct Data {
|
|||||||
byte_dice_id: u64,
|
byte_dice_id: u64,
|
||||||
reddit_data: Mutex<Option<Value>>,
|
reddit_data: Mutex<Option<Value>>,
|
||||||
discord_data: Mutex<Option<Value>>,
|
discord_data: Mutex<Option<Value>>,
|
||||||
|
bk_mods_json: Value,
|
||||||
args: Args
|
args: Args
|
||||||
// TODO: schedules
|
// TODO: schedules
|
||||||
}
|
}
|
||||||
@@ -66,6 +66,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.py && !args.rs {
|
if args.py && !args.rs {
|
||||||
println!("----- PYTHON ONLY MODE -----");
|
println!("----- PYTHON ONLY MODE -----");
|
||||||
@@ -116,12 +117,15 @@ async fn start(args: Args) {
|
|||||||
async fn gen_data(args: Args) -> Data {
|
async fn gen_data(args: Args) -> Data {
|
||||||
let ball_classic_str = std::fs::read_to_string("./data/8-ball_classic.txt").unwrap();
|
let ball_classic_str = std::fs::read_to_string("./data/8-ball_classic.txt").unwrap();
|
||||||
let ball_quirk_str = std::fs::read_to_string("./data/8-ball_quirky.txt").unwrap();
|
let ball_quirk_str = std::fs::read_to_string("./data/8-ball_quirky.txt").unwrap();
|
||||||
|
let bk_mods_str = std::fs::read_to_string("./data/bk_mods.json").unwrap();
|
||||||
|
|
||||||
let ball_classic: Vec<String> = ball_classic_str.lines().map(String::from).collect();
|
let ball_classic: Vec<String> = ball_classic_str.lines().map(String::from).collect();
|
||||||
let ball_quirk: Vec<String> = ball_quirk_str .lines().map(String::from).collect();
|
let ball_quirk: Vec<String> = ball_quirk_str .lines().map(String::from).collect();
|
||||||
|
let bk_mods: Value = serde_json::from_str(&bk_mods_str).unwrap();
|
||||||
|
|
||||||
let data = Data {
|
let data = Data {
|
||||||
ball_prompts: [ball_classic, ball_quirk],
|
ball_prompts: [ball_classic, ball_quirk],
|
||||||
|
bk_mods_json: bk_mods,
|
||||||
byte_dice_id: 697149665166229614,
|
byte_dice_id: 697149665166229614,
|
||||||
reddit_data: None.into(),
|
reddit_data: None.into(),
|
||||||
discord_data: None.into(),
|
discord_data: None.into(),
|
||||||
@@ -168,9 +172,9 @@ async fn gen_bot(data: Data, args: Args) -> Client {
|
|||||||
bk_week_cmds::bk_week_add(),
|
bk_week_cmds::bk_week_add(),
|
||||||
bk_week_cmds::bk_week_remove(),
|
bk_week_cmds::bk_week_remove(),
|
||||||
bk_week_cmds::bk_week_approve(),
|
bk_week_cmds::bk_week_approve(),
|
||||||
bk_week_cmds::bk_week_disapprove(),
|
bk_week_cmds::bk_admin_bind(),
|
||||||
bk_week_cmds::bk_week_bind(),
|
bk_week_cmds::bk_week_update(),
|
||||||
bk_week_cmds::bk_week_update()
|
bk_week_cmds::bk_week_vote()
|
||||||
],
|
],
|
||||||
event_handler: events::event_handler,
|
event_handler: events::event_handler,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
|
|||||||
+24
-3
@@ -137,15 +137,25 @@ pub async fn edit_msg(
|
|||||||
|
|
||||||
pub fn embed_post(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions {
|
pub fn embed_post(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions {
|
||||||
let media_type = &post_data["post_data"]["media_type"];
|
let media_type = &post_data["post_data"]["media_type"];
|
||||||
|
let re_votes = &post_data["votes"]["voters_re"].as_array().unwrap().len();
|
||||||
|
let dc_votes = &post_data["votes"]["voters_dc"].as_array().unwrap().len();
|
||||||
|
|
||||||
let desc_str = format!(
|
let desc_str = format!(
|
||||||
r#"Sorted by what I think will be most important
|
r#"Sorted by what I think will be most important
|
||||||
Spoilers and vote length anonymizer for fair review!
|
Spoilers and vote length anonymizer for fair review!
|
||||||
## Post Data:
|
## Post Data:
|
||||||
**Media type:** `{}`
|
**Media type:** `{}`
|
||||||
**Upvotes:** ||`{:>6}`||
|
**Post upvotes:** ||`{:>6}`||
|
||||||
**URL:** ||<{}>||
|
**URL:** ||<{}>||
|
||||||
**Media URLS:**
|
**Media URLS:**
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
## Voting data:
|
||||||
|
**Moderator votes:** ||`{:>6}`||
|
||||||
|
**Community votes:** ||`{:>6}`||
|
||||||
|
* ||**From Reddit:** `{:>6}`||
|
||||||
|
* ||**From Discord:** `{:>6}`||
|
||||||
|
|
||||||
## Listing Data:
|
## Listing Data:
|
||||||
**Added by:** `{{ human: {}, bot: {} }}`
|
**Added by:** `{{ human: {}, bot: {} }}`
|
||||||
**Approved by:** `{{ human: {}, bot: [not implemented] }}`"#,
|
**Approved by:** `{{ human: {}, bot: [not implemented] }}`"#,
|
||||||
@@ -153,6 +163,12 @@ pub fn embed_post(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions
|
|||||||
post_data["post_data"]["upvotes"].as_i64().unwrap(),
|
post_data["post_data"]["upvotes"].as_i64().unwrap(),
|
||||||
url,
|
url,
|
||||||
post_data["post_data"]["media_urls"].as_array().unwrap().iter().map(|s| format!("* ||<{}>||", s.as_str().unwrap())).collect::<Vec<_>>().join("\n"),
|
post_data["post_data"]["media_urls"].as_array().unwrap().iter().map(|s| format!("* ||<{}>||", s.as_str().unwrap())).collect::<Vec<_>>().join("\n"),
|
||||||
|
|
||||||
|
post_data["votes"]["mod_voters"].as_array().unwrap().len(),
|
||||||
|
re_votes + dc_votes,
|
||||||
|
re_votes,
|
||||||
|
dc_votes,
|
||||||
|
|
||||||
if post_data["added"] ["by_human"].as_bool().unwrap() { "✅" } else { "❌" },
|
if post_data["added"] ["by_human"].as_bool().unwrap() { "✅" } else { "❌" },
|
||||||
if post_data["added"] ["by_bot"].as_bool().unwrap() { "✅" } else { "❌" },
|
if post_data["added"] ["by_bot"].as_bool().unwrap() { "✅" } else { "❌" },
|
||||||
if post_data["approved"]["by_human"].as_bool().unwrap() { "✅" } else { "❌" }
|
if post_data["approved"]["by_human"].as_bool().unwrap() { "✅" } else { "❌" }
|
||||||
@@ -169,7 +185,7 @@ pub fn embed_post(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions
|
|||||||
|
|
||||||
return EmbedOptions {
|
return EmbedOptions {
|
||||||
title: Some(post_data["post_data"]["title"].as_str().unwrap().to_string()),
|
title: Some(post_data["post_data"]["title"].as_str().unwrap().to_string()),
|
||||||
desc: format!("{}\nJSON: ||`{}`||", trimmed, serde_json::to_string(&json_min).unwrap()),
|
desc: format!("{}\n\nJSON: ||`{}`||", trimmed, serde_json::to_string(&json_min).unwrap()),
|
||||||
col: Some(DEFAULT_DC_COL),
|
col: Some(DEFAULT_DC_COL),
|
||||||
url: Some(url.to_string()),
|
url: Some(url.to_string()),
|
||||||
ts: Some(Timestamp::from_unix_timestamp(post_data["post_data"]["date_unix"].as_i64().unwrap()).unwrap()),
|
ts: Some(Timestamp::from_unix_timestamp(post_data["post_data"]["date_unix"].as_i64().unwrap()).unwrap()),
|
||||||
@@ -185,7 +201,12 @@ pub fn embed_post(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions
|
|||||||
pub fn embed_post_removed(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions {
|
pub fn embed_post_removed(post_data: &Value, url: &str, empheral: bool) -> EmbedOptions {
|
||||||
return EmbedOptions {
|
return EmbedOptions {
|
||||||
title: Some("REMOVED!".to_string()),
|
title: Some("REMOVED!".to_string()),
|
||||||
desc: format!("## Removed by `{}`\nJSON: ||`{}`||", post_data["removed_by"].as_str().unwrap(), serde_json::to_string(&post_data).unwrap()),
|
desc: format!(
|
||||||
|
"## Removed by `{}`\n**Reason:** {}\n\nJSON: ||`{}`||",
|
||||||
|
post_data["removed_by"].as_str().unwrap(),
|
||||||
|
post_data["remove_reason"].as_str().unwrap(),
|
||||||
|
serde_json::to_string(&post_data).unwrap()
|
||||||
|
),
|
||||||
col: Some(REMOVED_DC_COL),
|
col: Some(REMOVED_DC_COL),
|
||||||
url: Some(url.to_string()),
|
url: Some(url.to_string()),
|
||||||
empheral,
|
empheral,
|
||||||
|
|||||||
+52
-14
@@ -18,7 +18,9 @@ class PostData:
|
|||||||
date_unix: int,
|
date_unix: int,
|
||||||
media_type: str,
|
media_type: str,
|
||||||
media_urls: list[str],
|
media_urls: list[str],
|
||||||
nominated_by_human: bool = False,
|
voters_re: list[str] = [],
|
||||||
|
voters_dc: list[int] = [],
|
||||||
|
mod_voters: list[int] = [],
|
||||||
added_by_human: bool = False,
|
added_by_human: bool = False,
|
||||||
added_by_bot: bool = False,
|
added_by_bot: bool = False,
|
||||||
approved_by_human: bool = False,
|
approved_by_human: bool = False,
|
||||||
@@ -30,7 +32,9 @@ class PostData:
|
|||||||
self.date_unix = date_unix
|
self.date_unix = date_unix
|
||||||
self.media_type = media_type
|
self.media_type = media_type
|
||||||
self.media_urls = media_urls
|
self.media_urls = media_urls
|
||||||
self.nominated_by_human = nominated_by_human
|
self.voters_re = voters_re
|
||||||
|
self.voters_dc = voters_dc
|
||||||
|
self.mod_voters = mod_voters
|
||||||
self.added_by_human = added_by_human
|
self.added_by_human = added_by_human
|
||||||
self.added_by_bot = added_by_bot
|
self.added_by_bot = added_by_bot
|
||||||
self.approved_by_human = approved_by_human
|
self.approved_by_human = approved_by_human
|
||||||
@@ -45,7 +49,11 @@ class PostData:
|
|||||||
"media_type": self.media_type,
|
"media_type": self.media_type,
|
||||||
"media_urls": self.media_urls
|
"media_urls": self.media_urls
|
||||||
},
|
},
|
||||||
"nominated_by_human": self.nominated_by_human,
|
"votes": {
|
||||||
|
"voters_re": self.voters_re,
|
||||||
|
"voters_dc": self.voters_dc,
|
||||||
|
"mod_voters": self.mod_voters
|
||||||
|
},
|
||||||
"added": {
|
"added": {
|
||||||
"by_human": self.added_by_human,
|
"by_human": self.added_by_human,
|
||||||
"by_bot": self.added_by_bot
|
"by_bot": self.added_by_bot
|
||||||
@@ -84,9 +92,6 @@ def read_data(bot: botPy.Bot) -> bool:
|
|||||||
json_data = json.loads(data_str)
|
json_data = json.loads(data_str)
|
||||||
bot.data = json_data
|
bot.data = json_data
|
||||||
|
|
||||||
if not bot.data["file_created_correctly"]:
|
|
||||||
raise Exception("reddit_data.json file wasn't created properly. Delete the file and retry.")
|
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
@@ -104,9 +109,8 @@ def add_post_to_data(bot: botPy.Bot, new_data: PostData, bypass_conditions: bool
|
|||||||
py_print(f"Added post \"{new_data.url}\" (Conditions bypassed)")
|
py_print(f"Added post \"{new_data.url}\" (Conditions bypassed)")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
# not sure what this is for
|
||||||
updated = False
|
updated = False
|
||||||
if "removed" not in bot.data[BK_WEEKLY][new_data.url]:
|
|
||||||
updated = new_data.upvotes != bot.data[BK_WEEKLY][new_data.url]["post_data"]
|
|
||||||
|
|
||||||
if new_data.url not in bot.data[BK_WEEKLY] or updated:
|
if new_data.url not in bot.data[BK_WEEKLY] or updated:
|
||||||
bot.data[BK_WEEKLY][new_data.url] = new_data.to_json()
|
bot.data[BK_WEEKLY][new_data.url] = new_data.to_json()
|
||||||
@@ -114,12 +118,11 @@ def add_post_to_data(bot: botPy.Bot, new_data: PostData, bypass_conditions: bool
|
|||||||
py_print(f"Added post \"{new_data.url}\"")
|
py_print(f"Added post \"{new_data.url}\"")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
elif "removed" in bot.data[BK_WEEKLY][new_data.url]:
|
if "removed" not in bot.data[BK_WEEKLY][new_data.url]:
|
||||||
py_print(f"Failed to add post \"{new_data.url}\": Removed flag is True.")
|
updated = new_data.upvotes != bot.data[BK_WEEKLY][new_data.url]["post_data"]
|
||||||
return False
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
py_print(f"Failed to add post \"{new_data.url}\": Already exists.")
|
py_print(f"Failed to add post \"{new_data.url}\": Removed flag is True.")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
@@ -131,9 +134,44 @@ def set_approve_post(bot: botPy.Bot, approved: bool, url: str) -> bool:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def remove_post(bot: botPy.Bot, url: str, removed_by: str = "UNKNOWN") -> bool:
|
def remove_post(bot: botPy.Bot, url: str, removed_by: str = "UNKNOWN", reason: str = "None") -> bool:
|
||||||
if url in bot.data[BK_WEEKLY]:
|
if url in bot.data[BK_WEEKLY]:
|
||||||
bot.data[BK_WEEKLY][url] = { "removed": True, "removed_by": removed_by }
|
bot.data[BK_WEEKLY][url] = { "removed": True, "removed_by": removed_by, "remove_reason": reason }
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def set_vote_post(
|
||||||
|
bot: botPy.Bot,
|
||||||
|
url: str,
|
||||||
|
user: str | int,
|
||||||
|
mod_vote: bool = False,
|
||||||
|
from_dc: bool = False,
|
||||||
|
remove_vote: bool = False,
|
||||||
|
) -> bool:
|
||||||
|
if url not in bot.data[BK_WEEKLY]:
|
||||||
|
return False
|
||||||
|
|
||||||
|
votes = bot.data[BK_WEEKLY][url]["votes"]
|
||||||
|
re_voters: set[str] = set(votes["voters_re"])
|
||||||
|
dc_voters: set[int] = set(votes["voters_dc"])
|
||||||
|
mod_voters: set[int] = set(votes["mod_voters"])
|
||||||
|
|
||||||
|
target_voters = mod_voters if mod_vote else (dc_voters if from_dc else re_voters)
|
||||||
|
|
||||||
|
if remove_vote:
|
||||||
|
if user not in target_voters:
|
||||||
|
return False
|
||||||
|
target_voters.remove(user)
|
||||||
|
|
||||||
|
else:
|
||||||
|
if user in target_voters:
|
||||||
|
return False
|
||||||
|
target_voters.add(user)
|
||||||
|
|
||||||
|
bot.data[BK_WEEKLY][url]["votes"]["voters_re"] = list(re_voters)
|
||||||
|
bot.data[BK_WEEKLY][url]["votes"]["voters_dc"] = list(dc_voters)
|
||||||
|
bot.data[BK_WEEKLY][url]["votes"]["mod_voters"] = list(mod_voters)
|
||||||
|
|
||||||
|
return True
|
||||||
@@ -50,7 +50,6 @@ async def add_new_posts(bot: botPy.Bot) -> bool:
|
|||||||
f" {without_media} had no media, " +
|
f" {without_media} had no media, " +
|
||||||
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)
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ async def json_to_func(v: dict, bot: botPy.Bot) -> dict:
|
|||||||
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"]))
|
||||||
|
case "set_vote_post": result = result_json(data.set_vote_post(bot, *v["args"]))
|
||||||
case "stop_praw": result = result_json(await bot.stop())
|
case "stop_praw": result = result_json(await bot.stop())
|
||||||
case _: value_supported = False
|
case _: value_supported = False
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user