(LARGE COMMIT) refactored until no errors
This commit is contained in:
@@ -5,7 +5,6 @@ An automation tool primarily made for myself (Byte Dice) but publicly available
|
|||||||
|
|
||||||
> [!CAUTION]
|
> [!CAUTION]
|
||||||
> This tool is not intended for public use outside of the official *Byte Dice Assistant* bots. Expect issues if you host this yourself.\
|
> This tool is not intended for public use outside of the official *Byte Dice Assistant* bots. Expect issues if you host this yourself.\
|
||||||
> This tool is only designed to run on Windows (10 and 11) and XUbuntu (24.04 and above) and may not work on any other OS.
|
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> This bot <ins>never modifies any Reddit content</ins>. All it does and will ever do is read/scrape.
|
> This bot <ins>never modifies any Reddit content</ins>. All it does and will ever do is read/scrape.
|
||||||
@@ -16,6 +15,21 @@ An automation tool primarily made for myself (Byte Dice) but publicly available
|
|||||||
**ByteDiceAssistant © 2025 by Byte Dice is licensed under CC BY-NC-SA 4.0.**\
|
**ByteDiceAssistant © 2025 by Byte Dice is licensed under CC BY-NC-SA 4.0.**\
|
||||||
**You can learn more about copyright by reading the full [license](/LICENSE.txt).**
|
**You can learn more about copyright by reading the full [license](/LICENSE.txt).**
|
||||||
|
|
||||||
|
## Environment variables:
|
||||||
|
(Any Reddit stuff can be disabled.)
|
||||||
|
|
||||||
|
| **Name** | **Description** |
|
||||||
|
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| `ASSISTANT_TOKEN` | The Discord bot token. (Create a Discord bot [here](https://discord.com/developers/docs/intro)!) |
|
||||||
|
| `ASSISTANT_TOKEN_TEST` | (Optional) A testing Discord bot token. This is only needed when the program is run with `-t` or `--test`. |
|
||||||
|
| `ASSISTANT_R_ID` | The id for the Reddit bot/account. (Create a Reddit bot [here](https://www.reddit.com/prefs/apps)!) |
|
||||||
|
| `ASSISTANT_R_TOKEN` | The token for the Reddit bot/account. |
|
||||||
|
| `ASSISTANT_R_NAME` | The username of the Reddit bot/account. |
|
||||||
|
| `ASSISTANT_R_PASS` | The password for the Reddit bot/account. |
|
||||||
|
| `ASSISTANT_OWNERS` | (OPTIONAL) A list of Discord user IDs that "own" the bot. Separate each ID with a single comma and **no** spaces. This will allow the specified user IDs to run root commands such as `/stop`, it will also DM these users when *certain* errors occur. |
|
||||||
|
| `ASSISTANT_BK_MODS` | (OPTIONAL) Same format as `ASSISTANT_OWNERS` but for people who are allowed to use the `/re_*` commands. |
|
||||||
|
|
||||||
|
<!--
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
| Name | Category | Description |
|
| Name | Category | Description |
|
||||||
@@ -44,18 +58,6 @@ An automation tool primarily made for myself (Byte Dice) but publicly available
|
|||||||
This program uses Rust (v1.82.0) and Python (v3.11.4), you can likely use other versions if they are compatible.\
|
This program uses Rust (v1.82.0) and Python (v3.11.4), you can likely use other versions if they are compatible.\
|
||||||
It is required to install all used Python modules. You can find those in [req.txt](/req.txt). Installation instructions are in the *How to start the program* section.
|
It is required to install all used Python modules. You can find those in [req.txt](/req.txt). Installation instructions are in the *How to start the program* section.
|
||||||
|
|
||||||
### Environment variables:
|
|
||||||
| **Name** | **Description** |
|
|
||||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
||||||
| `ASSISTANT_TOKEN` | The Discord bot token. (Create a Discord bot [here](https://discord.com/developers/docs/intro)!) |
|
|
||||||
| `ASSISTANT_TOKEN_TEST` | (Optional) A testing Discord bot token. This is only needed when the program is run with `-t` or `--test`. |
|
|
||||||
| `ASSISTANT_R_ID` | The id for the Reddit bot/account. (Create a Reddit bot [here](https://www.reddit.com/prefs/apps)!) |
|
|
||||||
| `ASSISTANT_R_TOKEN` | The token for the Reddit bot/account. |
|
|
||||||
| `ASSISTANT_R_NAME` | The username of the Reddit bot/account. |
|
|
||||||
| `ASSISTANT_R_PASS` | The password for the Reddit bot/account. |
|
|
||||||
| `ASSISTANT_OWNERS` | (OPTIONAL) A list of Discord user IDs that "own" the bot. Separate each ID with a single comma and **no** spaces. This will allow the specified user IDs to run root commands such as `/stop`, it will also DM these users when *certain* errors occur. |
|
|
||||||
| `ASSISTANT_BK_MODS` | (OPTIONAL) Same format as `ASSISTANT_OWNERS` but for people who are allowed to use the `/re_*` commands. |
|
|
||||||
|
|
||||||
### Required permissions:
|
### Required permissions:
|
||||||
**These are automatically set if you use the [official invite link](https://discord.com/oauth2/authorize?client_id=1212127255795335208&permissions=84992&integration_type=0&scope=bot) or an invite link with the permissions integer set to `84992`.** (The permission integer is this part of the URL `&permissions=84992`)
|
**These are automatically set if you use the [official invite link](https://discord.com/oauth2/authorize?client_id=1212127255795335208&permissions=84992&integration_type=0&scope=bot) or an invite link with the permissions integer set to `84992`.** (The permission integer is this part of the URL `&permissions=84992`)
|
||||||
* Create Invites
|
* Create Invites
|
||||||
@@ -89,3 +91,4 @@ You can find config files in the [cfg/](cfg/) folder. You can also find the defa
|
|||||||
* Run `$ cd path/to/extracted/folder`.
|
* Run `$ cd path/to/extracted/folder`.
|
||||||
* Run `$ cargo run`. You can view a list of options by running `$ cargo run -- --help` or `$ cargo run -- -h`.
|
* Run `$ cargo run`. You can view a list of options by running `$ cargo run -- --help` or `$ cargo run -- -h`.
|
||||||
* If you only want to run the Python code, you can either run `$ cargo run -- --py`, or `$ python ./src/python/main.py`. The second option is recommended for better performance.
|
* If you only want to run the Python code, you can either run `$ cargo run -- --py`, or `$ python ./src/python/main.py`. The second option is recommended for better performance.
|
||||||
|
-->
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{Context, Error, db_cmds::{add_server, reddit_channel, wwrps_channel}};
|
use crate::{Context, Error, cmds::db::{add_server, reddit_channel, wwrps_channel}};
|
||||||
|
|
||||||
|
|
||||||
#[derive(poise::ChoiceParameter, PartialEq)]
|
#[derive(poise::ChoiceParameter, PartialEq)]
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use rand::{seq::IteratorRandom, Rng};
|
use rand::{seq::IteratorRandom, Rng};
|
||||||
|
|
||||||
use crate::{db::generic::get_toml_mutex, lang, messages::send_msg, Context, Error};
|
use crate::{lang, messages::send_msg, Context, Error};
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
@@ -16,7 +16,9 @@ pub async fn cmd(
|
|||||||
#[description = "Question to ask."] question: String
|
#[description = "Question to ask."] question: String
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
let quirky_chance = get_toml_mutex(&ctx.data().cfg).await.unwrap()["commands"]["eight_ball_quirky_chance"].as_float().unwrap();
|
let quirky_chance = &ctx.data().cfg
|
||||||
|
["commands"]["eight_ball_quirky_chance"]
|
||||||
|
.as_float().unwrap();
|
||||||
let is_quirky = rand::rng().random_bool(quirky_chance.clamp(0.0, 1.0));
|
let is_quirky = rand::rng().random_bool(quirky_chance.clamp(0.0, 1.0));
|
||||||
let list = &ctx.data().ball_prompts[if is_quirky { 1 } else { 0 }];
|
let list = &ctx.data().ball_prompts[if is_quirky { 1 } else { 0 }];
|
||||||
let rand_item = list.iter().choose(&mut rand::rng());
|
let rand_item = list.iter().choose(&mut rand::rng());
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use poise::serenity_prelude::{ChannelId, Mentionable};
|
use poise::serenity_prelude::{ChannelId, Mentionable};
|
||||||
use tokio::sync::MutexGuard;
|
use tokio::sync::MutexGuard;
|
||||||
|
|
||||||
use crate::{Context, Error, db::generic::get_json_mutex, games::wwrps::{RPS, RPSGame, RPSPlayer}, lang, messages::{http_send_msg, send_msg}};
|
use crate::{Context, Error, games::wwrps::{RPS, RPSGame, RPSPlayer}, lang, messages::{http_send_msg, send_msg}};
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
@@ -75,7 +75,7 @@ fn results_text(game: &MutexGuard<'_, RPSGame>) -> String {
|
|||||||
|
|
||||||
|
|
||||||
async fn get_wwrps_channel(ctx: Context<'_>) -> Option<u64> {
|
async fn get_wwrps_channel(ctx: Context<'_>) -> Option<u64> {
|
||||||
let d = get_json_mutex(&ctx.data().discord_data).await.unwrap();
|
let d = &ctx.data().discord_data.lock().await;
|
||||||
|
|
||||||
let is_guild = ctx.guild_channel().await.is_some();
|
let is_guild = ctx.guild_channel().await.is_some();
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::db::generic::get_json_mutex;
|
|
||||||
use crate::db::reddit::{self, POSTS_KEY};
|
use crate::db::reddit::{self, POSTS_KEY};
|
||||||
use crate::messages::send_msg;
|
use crate::messages::send_msg;
|
||||||
use crate::re_cmds::get::get_post_from_data;
|
use crate::cmds::reddit::get::get_post_from_data;
|
||||||
use crate::{websocket::send_cmd_json, Context, Error};
|
use crate::{websocket::send_cmd_json, Context, Error};
|
||||||
use crate::re_cmds::generic_fns::{is_bk_mod_msg, send_embed_for_post, to_shorturl};
|
use crate::cmds::reddit::generic_fns::{is_bk_mod_msg, send_embed_for_post, to_shorturl};
|
||||||
use crate::lang;
|
use crate::lang;
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
@@ -42,8 +41,8 @@ pub async fn cmd(
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
reddit::update_data(ctx.data()).await;
|
reddit::update_data().await;
|
||||||
let reddit_data = get_json_mutex(&ctx.data().reddit_data).await?;
|
let reddit_data = &ctx.data().reddit_data.lock().await;
|
||||||
|
|
||||||
if let Some(bk_week) = reddit_data.get(POSTS_KEY) {
|
if let Some(bk_week) = reddit_data.get(POSTS_KEY) {
|
||||||
if let Some(post) = bk_week.get(shorturl) {
|
if let Some(post) = bk_week.get(shorturl) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
use crate::{Context, Error, db::{generic::get_json_mutex, reddit::{self, POSTS_KEY}}, lang, messages::send_msg, re_cmds::generic_fns::{is_bk_mod_msg, to_shorturl}, websocket};
|
use crate::{Context, Error, db::{reddit::POSTS_KEY}, lang, messages::send_msg, cmds::reddit::generic_fns::{is_bk_mod_msg, to_shorturl}, websocket};
|
||||||
|
|
||||||
use super::generic_fns::send_embed_for_removed;
|
use super::generic_fns::send_embed_for_removed;
|
||||||
|
|
||||||
@@ -23,8 +23,7 @@ pub async fn cmd(
|
|||||||
let shorturl_u = to_shorturl(&url);
|
let shorturl_u = to_shorturl(&url);
|
||||||
let shorturl = &shorturl_u.unwrap_or(url.clone());
|
let shorturl = &shorturl_u.unwrap_or(url.clone());
|
||||||
|
|
||||||
reddit::update_data(ctx.data()).await;
|
let reddit_data = &ctx.data().reddit_data.lock().await;
|
||||||
let reddit_data = get_json_mutex(&ctx.data().reddit_data).await?;
|
|
||||||
|
|
||||||
approve_cmd(ctx, shorturl, &reddit_data, !disapprove.unwrap_or(false)).await;
|
approve_cmd(ctx, shorturl, &reddit_data, !disapprove.unwrap_or(false)).await;
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ use poise::serenity_prelude::{self as serenity, ChannelId, ComponentInteraction,
|
|||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{Context, Data, Error, db::generic::get_toml_mutex, lang, messages::{EmbedOptions, JSON_TEXT_END, JSON_TEXT_START, decode_and_decompress_json, embed_from_options, make_post_embed, make_removed_embed, send_embed, send_msg}};
|
use crate::{Context, Data, Error, lang, messages::{EmbedOptions, JSON_TEXT_END, JSON_TEXT_START, decode_and_decompress_json, embed_from_options, make_post_embed, make_removed_embed, send_embed, send_msg}};
|
||||||
|
|
||||||
pub fn is_bk_mod(mod_list: Vec<u64>, uid: u64) -> bool {
|
pub fn is_bk_mod(mod_list: Vec<u64>, uid: u64) -> bool {
|
||||||
return mod_list.contains(&uid);
|
return mod_list.contains(&uid);
|
||||||
@@ -10,7 +10,7 @@ pub fn is_bk_mod(mod_list: Vec<u64>, uid: u64) -> bool {
|
|||||||
|
|
||||||
|
|
||||||
pub async fn is_bk_mod_msg(ctx: Context<'_>) -> bool {
|
pub async fn is_bk_mod_msg(ctx: Context<'_>) -> bool {
|
||||||
if is_bk_mod(ctx.data().bk_mods.clone(), ctx.author().id.get()) { return true; }
|
if is_bk_mod(ctx.data().env_vars.reddit_mod_discord_ids.clone(), ctx.author().id.get()) { return true; }
|
||||||
|
|
||||||
let sr = get_readable_subreddits(ctx.data()).await.unwrap();
|
let sr = get_readable_subreddits(ctx.data()).await.unwrap();
|
||||||
send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod", sr), true, true).await;
|
send_msg(ctx, lang!("dc_msg_re_permdeny_not_re_mod", sr), true, true).await;
|
||||||
@@ -19,7 +19,7 @@ pub async fn is_bk_mod_msg(ctx: Context<'_>) -> bool {
|
|||||||
|
|
||||||
|
|
||||||
pub async fn is_bk_mod_serenity(ctx: &serenity::Context, data: &Data, author: &Member, component: &ComponentInteraction) -> bool {
|
pub async fn is_bk_mod_serenity(ctx: &serenity::Context, data: &Data, author: &Member, component: &ComponentInteraction) -> bool {
|
||||||
if is_bk_mod(data.bk_mods.clone(), author.user.id.get()) { return true; }
|
if is_bk_mod(data.env_vars.reddit_mod_discord_ids.clone(), author.user.id.get()) { return true; }
|
||||||
|
|
||||||
let sr = get_readable_subreddits(data).await.unwrap();
|
let sr = get_readable_subreddits(data).await.unwrap();
|
||||||
serenity_send_msg(ctx, component, lang!("dc_msg_re_permdeny_not_re_mod", sr), true).await;
|
serenity_send_msg(ctx, component, lang!("dc_msg_re_permdeny_not_re_mod", sr), true).await;
|
||||||
@@ -70,8 +70,7 @@ pub async fn send_embed_for_removed(ctx: Context<'_>, url: &str, post: &Value) {
|
|||||||
|
|
||||||
|
|
||||||
pub async fn get_readable_subreddits(data: &Data) -> Result<String, Error> {
|
pub async fn get_readable_subreddits(data: &Data) -> Result<String, Error> {
|
||||||
let d = get_toml_mutex(&data.cfg).await.unwrap();
|
let sr = data.cfg["reddit"]["subreddits"].as_array().unwrap();
|
||||||
let sr = d["reddit"]["subreddits"].as_array().unwrap();
|
|
||||||
let sr_str: Vec<&str> = sr
|
let sr_str: Vec<&str> = sr
|
||||||
.iter()
|
.iter()
|
||||||
.map(|v| v.as_str().unwrap())
|
.map(|v| v.as_str().unwrap())
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{Context, Error, db::{generic::get_json_mutex, reddit::{self, POSTS_KEY}}, lang, messages::send_msg, re_cmds::generic_fns::{send_embed_for_post, to_shorturl}, rs_println};
|
use crate::{Context, Error, db::{reddit::{self, POSTS_KEY}}, lang, messages::send_msg, cmds::reddit::generic_fns::{send_embed_for_post, to_shorturl}, rs_println};
|
||||||
|
|
||||||
use super::generic_fns::send_embed_for_removed;
|
use super::generic_fns::send_embed_for_removed;
|
||||||
|
|
||||||
@@ -17,12 +17,12 @@ pub async fn cmd(
|
|||||||
#[description = "The post URL."] url: String
|
#[description = "The post URL."] url: String
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
reddit::update_data(ctx.data()).await;
|
reddit::update_data().await;
|
||||||
|
|
||||||
let shorturl_u = to_shorturl(&url);
|
let shorturl_u = to_shorturl(&url);
|
||||||
let shorturl = &shorturl_u.unwrap_or(url.clone());
|
let shorturl = &shorturl_u.unwrap_or(url.clone());
|
||||||
|
|
||||||
let reddit_data = get_json_mutex(&ctx.data().reddit_data).await?;
|
let reddit_data = &ctx.data().reddit_data.lock().await;
|
||||||
|
|
||||||
if let Some(post) = get_post_from_data(ctx, &reddit_data, shorturl).await? {
|
if let Some(post) = get_post_from_data(ctx, &reddit_data, shorturl).await? {
|
||||||
send_embed_for_post(ctx, post, shorturl).await?;
|
send_embed_for_post(ctx, post, shorturl).await?;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::{Context, Error, db::{generic::get_json_mutex, reddit}, lang, messages::send_msg, re_cmds::{generic_fns::{is_bk_mod_msg, send_embed_for_removed, to_shorturl}, get::get_post_from_data}, websocket::send_cmd_json};
|
use crate::{Context, Error, db::reddit, lang, messages::send_msg, cmds::reddit::{generic_fns::{is_bk_mod_msg, send_embed_for_removed, to_shorturl}, get::get_post_from_data}, websocket::send_cmd_json};
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
slash_command,
|
slash_command,
|
||||||
@@ -36,8 +36,8 @@ pub async fn cmd(
|
|||||||
send_msg(ctx, lang!("dc_msg_re_post_404"), true, true).await;
|
send_msg(ctx, lang!("dc_msg_re_post_404"), true, true).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
reddit::update_data(ctx.data()).await;
|
reddit::update_data().await;
|
||||||
let reddit_data = get_json_mutex(&ctx.data().reddit_data).await?;
|
let reddit_data = &ctx.data().reddit_data.lock().await;
|
||||||
|
|
||||||
if let Some(post) = get_post_from_data(ctx, &reddit_data, shorturl).await? {
|
if let Some(post) = get_post_from_data(ctx, &reddit_data, shorturl).await? {
|
||||||
if post["removed"]["removed"].as_bool().unwrap() {
|
if post["removed"]["removed"].as_bool().unwrap() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use crate::{lang, messages::send_msg, re_cmds::generic_fns::to_shorturl, Context, Error};
|
use crate::{lang, messages::send_msg, cmds::reddit::generic_fns::to_shorturl, Context, Error};
|
||||||
|
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{Context, Error, db::{generic::get_json_mutex, reddit::POSTS_KEY}, re_cmds::generic_fns::send_embed_for_post};
|
use crate::{Context, Error, db::reddit::POSTS_KEY, cmds::reddit::generic_fns::send_embed_for_post};
|
||||||
|
|
||||||
#[derive(poise::ChoiceParameter, PartialEq)]
|
#[derive(poise::ChoiceParameter, PartialEq)]
|
||||||
enum TopCategory {
|
enum TopCategory {
|
||||||
@@ -30,7 +30,7 @@ pub async fn cmd(
|
|||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
let mut all: HashMap<&str, i32> = HashMap::new();
|
let mut all: HashMap<&str, i32> = HashMap::new();
|
||||||
let posts = &get_json_mutex(&ctx.data().reddit_data).await?[POSTS_KEY];
|
let posts = &ctx.data().reddit_data.lock().await[POSTS_KEY];
|
||||||
let posts_u = posts.as_object().unwrap();
|
let posts_u = posts.as_object().unwrap();
|
||||||
|
|
||||||
for (url, dat) in posts_u {
|
for (url, dat) in posts_u {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ use std::time::{SystemTime, UNIX_EPOCH};
|
|||||||
use poise::{serenity_prelude::{ChannelId, EditMessage, GetMessages, Http, Message, MessageId, UserId}, ReplyHandle};
|
use poise::{serenity_prelude::{ChannelId, EditMessage, GetMessages, Http, Message, MessageId, UserId}, ReplyHandle};
|
||||||
use serde_json::{json, Map, Value};
|
use serde_json::{json, Map, Value};
|
||||||
|
|
||||||
use crate::{Context, Error, db::{discord::contains_server, generic::{get_json_mutex, get_toml_mutex}, keys::DC_POSTS_CHANNEL_KEY, reddit::{self, POSTS_KEY}}, lang, messages::{edit_reply, embed_from_options, make_post_embed, make_removed_embed, send_embed, send_msg, trim_post_json}, re_cmds::generic_fns::embed_to_json, rs_println, websocket::send_cmd_json};
|
use crate::{Context, Error, db::{discord::contains_server, keys::DC_POSTS_CHANNEL_KEY, reddit::{self, POSTS_KEY}}, lang, messages::{edit_reply, embed_from_options, make_post_embed, make_removed_embed, send_embed, send_msg, trim_post_json}, cmds::reddit::generic_fns::embed_to_json, rs_println, websocket::send_cmd_json};
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
slash_command,
|
slash_command,
|
||||||
@@ -39,13 +39,12 @@ pub async fn cmd(
|
|||||||
let max_age_u = max_age.unwrap_or(8);
|
let max_age_u = max_age.unwrap_or(8);
|
||||||
let max_age_secs = max_age_u as u64 * (60 * 60 * 24);
|
let max_age_secs = max_age_u as u64 * (60 * 60 * 24);
|
||||||
|
|
||||||
let max_results_toml = &get_toml_mutex(&ctx.data().cfg).await.unwrap();
|
let max_results_pre = ctx.data().cfg["reddit"]["fetch_limit"].as_integer().unwrap();
|
||||||
let max_results_pre = max_results_toml["reddit"]["fetch_limit"].as_integer().unwrap();
|
|
||||||
let max_results_final = max_results.unwrap_or(max_results_pre as u16);
|
let max_results_final = max_results.unwrap_or(max_results_pre as u16);
|
||||||
|
|
||||||
send_cmd_json("add_new_posts", Some(json!([max_age_secs, max_results_final])), true).await;
|
send_cmd_json("add_new_posts", Some(json!([max_age_secs, max_results_final])), true).await;
|
||||||
reddit::update_data(ctx.data()).await;
|
reddit::update_data().await;
|
||||||
let r_data = get_json_mutex(&ctx.data().reddit_data).await?;
|
let r_data = &ctx.data().reddit_data.lock().await;
|
||||||
|
|
||||||
let c_id_u = get_c_id(ctx).await;
|
let c_id_u = get_c_id(ctx).await;
|
||||||
|
|
||||||
@@ -118,7 +117,7 @@ async fn get_c_id(ctx: Context<'_>) -> Option<ChannelId> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let d = get_json_mutex(&ctx.data().discord_data).await.unwrap();
|
let d = &ctx.data().discord_data.lock().await;
|
||||||
let c_id_u =
|
let c_id_u =
|
||||||
d["servers"]
|
d["servers"]
|
||||||
[ctx.guild_id().unwrap().to_string()]
|
[ctx.guild_id().unwrap().to_string()]
|
||||||
|
|||||||
+12
-16
@@ -1,6 +1,6 @@
|
|||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
|
|
||||||
use crate::{Context, Error, db::{generic::get_json_mutex, reddit::{self, POSTS_KEY}}, lang, messages::send_msg, re_cmds::generic_fns::{is_bk_mod, send_embed_for_removed, to_shorturl}, websocket::send_cmd_json};
|
use crate::{Context, Error, db::reddit::{self, POSTS_KEY}, lang, messages::send_msg, cmds::reddit::generic_fns::{is_bk_mod, send_embed_for_removed, to_shorturl}, websocket::send_cmd_json};
|
||||||
|
|
||||||
#[poise::command(
|
#[poise::command(
|
||||||
slash_command,
|
slash_command,
|
||||||
@@ -16,9 +16,9 @@ pub async fn cmd(
|
|||||||
#[description = "Wether to undo your vote or not"] un_vote: Option<bool>
|
#[description = "Wether to undo your vote or not"] un_vote: Option<bool>
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
{
|
{
|
||||||
reddit::update_data(ctx.data()).await;
|
reddit::update_data().await;
|
||||||
let uid = ctx.author().id.get();
|
let uid = ctx.author().id.get();
|
||||||
let re_data = get_json_mutex(&ctx.data().reddit_data).await?;
|
let re_data = &ctx.data().reddit_data.lock().await;
|
||||||
let post_data = re_data[POSTS_KEY].clone();
|
let post_data = re_data[POSTS_KEY].clone();
|
||||||
let unw_vote = un_vote.unwrap_or(false);
|
let unw_vote = un_vote.unwrap_or(false);
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ pub async fn cmd(
|
|||||||
|
|
||||||
let url_data = &post_data[&shorturl];
|
let url_data = &post_data[&shorturl];
|
||||||
|
|
||||||
let is_mod = is_bk_mod(ctx.data().bk_mods.clone(), ctx.author().id.get());
|
let is_mod = is_bk_mod(ctx.data().env_vars.reddit_mod_discord_ids.clone(), ctx.author().id.get());
|
||||||
let voters_dc = url_data["votes"]["voters_dc"].as_array().unwrap();
|
let voters_dc = url_data["votes"]["voters_dc"].as_array().unwrap();
|
||||||
let mod_voters = url_data["votes"]["mod_voters"].as_array().unwrap();
|
let mod_voters = url_data["votes"]["mod_voters"].as_array().unwrap();
|
||||||
let voters = if is_mod { mod_voters } else { voters_dc };
|
let voters = if is_mod { mod_voters } else { voters_dc };
|
||||||
@@ -53,18 +53,14 @@ pub async fn cmd(
|
|||||||
let r = send_cmd_json("set_vote_post", Some(json!([shorturl, uid, is_mod, true, unw_vote])), true).await.unwrap();
|
let r = send_cmd_json("set_vote_post", Some(json!([shorturl, uid, is_mod, true, unw_vote])), true).await.unwrap();
|
||||||
let unw_r = r["value"].as_bool().unwrap();
|
let unw_r = r["value"].as_bool().unwrap();
|
||||||
|
|
||||||
if unw_r && !unw_vote && is_mod {
|
if unw_r && !unw_vote && is_mod
|
||||||
send_msg(ctx, lang!("dc_msg_re_vote_mod_success"), true, true).await;
|
{ send_msg(ctx, lang!("dc_msg_re_vote_mod_success"), true, true).await; }
|
||||||
}
|
else if unw_r && !unw_vote && !is_mod
|
||||||
else if unw_r && !unw_vote && !is_mod {
|
{ send_msg(ctx, lang!("dc_msg_re_vote_success"), true, true).await; }
|
||||||
send_msg(ctx, lang!("dc_msg_re_vote_success"), true, true).await;
|
else if unw_r && unw_vote
|
||||||
}
|
{ send_msg(ctx, lang!("dc_msg_re_vote_remove_success"), true, true).await; }
|
||||||
else if unw_r && unw_vote {
|
else
|
||||||
send_msg(ctx, lang!("dc_msg_re_vote_remove_success"), true, true).await;
|
{ send_msg(ctx, lang!("dc_msg_re_vote_err"), true, true).await; }
|
||||||
}
|
|
||||||
else {
|
|
||||||
send_msg(ctx, lang!("dc_msg_re_vote_err"), true, true).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
pub mod bot_data;
|
pub mod bot_data;
|
||||||
pub mod cfg;
|
pub mod cfg;
|
||||||
pub mod terminal_args;
|
|
||||||
pub mod discord;
|
pub mod discord;
|
||||||
pub mod generic;
|
pub mod env_vars;
|
||||||
pub mod keys;
|
pub mod keys;
|
||||||
pub mod reddit;
|
pub mod reddit;
|
||||||
|
pub mod terminal_args;
|
||||||
+9
-10
@@ -1,18 +1,17 @@
|
|||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::{db::terminal_args::Args, games::wwrps::RPSGame, lang::Lang};
|
use crate::{db::{env_vars::AssistantEnv, terminal_args::Args}, games::wwrps::RPSGame, lang::Lang};
|
||||||
|
|
||||||
|
|
||||||
pub struct Data {
|
pub struct Data {
|
||||||
pub owners: Vec<u64>,
|
|
||||||
pub ball_prompts: [Vec<String>; 2],
|
|
||||||
pub rps_game: Mutex<RPSGame>,
|
|
||||||
pub reddit_data: Mutex<Option<Value>>,
|
|
||||||
pub discord_data: Mutex<Option<Value>>,
|
|
||||||
pub cfg: Mutex<Option<toml::Value>>,
|
|
||||||
pub bk_mods: Vec<u64>,
|
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
pub lang_name: Mutex<String>,
|
pub ball_prompts: [Vec<String>; 2],
|
||||||
pub lang: Mutex<Lang>
|
pub cfg: toml::Value,
|
||||||
|
pub discord_data: Mutex<Value>,
|
||||||
|
pub env_vars: AssistantEnv,
|
||||||
|
pub lang_name: String,
|
||||||
|
pub lang: Lang,
|
||||||
|
pub reddit_data: Mutex<Value>,
|
||||||
|
pub rps_game: Mutex<RPSGame>,
|
||||||
}
|
}
|
||||||
+5
-9
@@ -1,15 +1,13 @@
|
|||||||
use std::{fs, io::Write, path::Path};
|
use std::{fs, io::Write, path::Path};
|
||||||
|
|
||||||
use serde_json::{Value, json};
|
use crate::rs_println;
|
||||||
|
|
||||||
use crate::{Data, rs_println, websocket::send_cmd_json};
|
|
||||||
|
|
||||||
|
|
||||||
static DATA_PATH: &str = "./cfg/cfg.toml";
|
static DATA_PATH: &str = "./cfg/cfg.toml";
|
||||||
static PRESET_PATH: &str = "./data/defaults/cfg_default.toml";
|
static PRESET_PATH: &str = "./data/defaults/cfg_default.toml";
|
||||||
|
|
||||||
|
|
||||||
pub async fn read_data(data: &Data, wipe: bool) -> Option<Value> {
|
pub async fn read_data(wipe: bool) -> toml::Value {
|
||||||
if !Path::new(DATA_PATH).exists() || wipe {
|
if !Path::new(DATA_PATH).exists() || wipe {
|
||||||
rs_println!(
|
rs_println!(
|
||||||
"{} creating new from preset...",
|
"{} creating new from preset...",
|
||||||
@@ -20,16 +18,14 @@ pub async fn read_data(data: &Data, wipe: bool) -> Option<Value> {
|
|||||||
|
|
||||||
let str_data = fs::read_to_string(DATA_PATH).unwrap();
|
let str_data = fs::read_to_string(DATA_PATH).unwrap();
|
||||||
let json_data: toml::Value = str_data.parse().unwrap();
|
let json_data: toml::Value = str_data.parse().unwrap();
|
||||||
let mut cfg_data = data.cfg.lock().await;
|
|
||||||
*cfg_data = Some(json_data.clone());
|
|
||||||
|
|
||||||
let r = send_cmd_json(
|
/*let r = send_cmd_json(
|
||||||
"update_cfg",
|
"update_cfg",
|
||||||
Some(json!([toml::to_string(&json_data).unwrap()])),
|
Some(json!([toml::to_string(&json_data).unwrap()])),
|
||||||
true
|
true
|
||||||
).await;
|
).await;*/
|
||||||
|
|
||||||
return r;
|
return json_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+8
-14
@@ -8,7 +8,7 @@ static DATA_PATH: &str = "./data/db/dc_data.json";
|
|||||||
static PRESET_PATH: &str = "./data/defaults/dc_data_preset.json";
|
static PRESET_PATH: &str = "./data/defaults/dc_data_preset.json";
|
||||||
|
|
||||||
|
|
||||||
pub async fn read_data(data: &Data, wipe: bool) {
|
pub async fn read_data(wipe: bool) -> Value {
|
||||||
if !Path::new(DATA_PATH).exists() || wipe {
|
if !Path::new(DATA_PATH).exists() || wipe {
|
||||||
rs_println!(
|
rs_println!(
|
||||||
"{} creating new from preset...",
|
"{} creating new from preset...",
|
||||||
@@ -19,8 +19,7 @@ pub async fn read_data(data: &Data, wipe: bool) {
|
|||||||
|
|
||||||
let str_data = fs::read_to_string(DATA_PATH).unwrap();
|
let str_data = fs::read_to_string(DATA_PATH).unwrap();
|
||||||
let json_data = serde_json::from_str(&str_data).unwrap();
|
let json_data = serde_json::from_str(&str_data).unwrap();
|
||||||
let mut dc_data = data.discord_data.lock().await;
|
return json_data;
|
||||||
*dc_data = json_data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -51,17 +50,15 @@ pub async fn write_data(data: &Data) {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
||||||
let mut dc_data_lock = data.discord_data.lock().await;
|
let dc_data = data.discord_data.lock().await;
|
||||||
let dc_data = dc_data_lock.as_mut().unwrap();
|
let json_str = serde_json::to_string_pretty(&dc_data.clone()).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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn add_server(data: &Data, server_id: u64) -> Result<(), ()> {
|
pub async fn add_server(data: &Data, server_id: u64) -> Result<(), ()> {
|
||||||
let mut dc_data_lock = data.discord_data.lock().await;
|
let mut dc_data = data.discord_data.lock().await;
|
||||||
let dc_data = dc_data_lock.as_mut().unwrap();
|
|
||||||
|
|
||||||
if dc_data.get("servers").is_none() { return Err(()); }
|
if dc_data.get("servers").is_none() { return Err(()); }
|
||||||
|
|
||||||
@@ -76,8 +73,7 @@ pub async fn add_server(data: &Data, server_id: u64) -> Result<(), ()> {
|
|||||||
|
|
||||||
|
|
||||||
pub async fn bind_bk(data: &Data, server_id: u64, channel_id: u64) -> Result<(), ()> {
|
pub async fn 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 = data.discord_data.lock().await;
|
||||||
let dc_data = dc_data_lock.as_mut().unwrap();
|
|
||||||
|
|
||||||
if dc_data.get("servers").is_none() { return Err(()); }
|
if dc_data.get("servers").is_none() { return Err(()); }
|
||||||
|
|
||||||
@@ -96,8 +92,7 @@ pub async fn bind_bk(data: &Data, server_id: u64, channel_id: u64) -> Result<(),
|
|||||||
|
|
||||||
|
|
||||||
pub async fn bind_wwrps(data: &Data, server_id: u64, channel_id: u64) -> Result<(), ()> {
|
pub async fn bind_wwrps(data: &Data, server_id: u64, channel_id: u64) -> Result<(), ()> {
|
||||||
let mut dc_data_lock = data.discord_data.lock().await;
|
let mut dc_data = data.discord_data.lock().await;
|
||||||
let dc_data = dc_data_lock.as_mut().unwrap();
|
|
||||||
|
|
||||||
if dc_data.get("servers").is_none() { return Err(()); }
|
if dc_data.get("servers").is_none() { return Err(()); }
|
||||||
|
|
||||||
@@ -115,8 +110,7 @@ pub async fn bind_wwrps(data: &Data, server_id: u64, channel_id: u64) -> Result<
|
|||||||
|
|
||||||
|
|
||||||
pub async fn contains_server(data: &Data, server_id: u64) -> bool {
|
pub async fn contains_server(data: &Data, server_id: u64) -> bool {
|
||||||
let dc_data_lock = data.discord_data.lock().await;
|
let dc_data = data.discord_data.lock().await;
|
||||||
let dc_data = dc_data_lock.as_ref().unwrap();
|
|
||||||
|
|
||||||
if dc_data.get("servers").is_none() { return false; }
|
if dc_data.get("servers").is_none() { return false; }
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
#[derive(Clone)]
|
||||||
|
pub struct AssistantEnv {
|
||||||
|
pub token: String,
|
||||||
|
pub bot_owners: Vec<u64>,
|
||||||
|
pub reddit_mod_discord_ids: Vec<u64>
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl AssistantEnv {
|
||||||
|
pub fn new(test: bool) -> Self {
|
||||||
|
let token_name = if test { "ASSISTANT_TOKEN" }
|
||||||
|
else { "ASSISTANT_TOKEN_TEST" };
|
||||||
|
|
||||||
|
return AssistantEnv {
|
||||||
|
token: string_env(token_name),
|
||||||
|
bot_owners: vec_u64_env("ASSISTANT_OWNERS"),
|
||||||
|
reddit_mod_discord_ids: vec_u64_env("ASSISTANT_BK_MODS")
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn string_env(name: &str) -> String {
|
||||||
|
return std::env::var(name)
|
||||||
|
.expect(format!("Environment variable \"{}\" not found!", name).as_str())
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn vec_u64_env(name: &str) -> Vec<u64> {
|
||||||
|
let var = std::env::var(name)
|
||||||
|
.unwrap_or("0".to_string());
|
||||||
|
|
||||||
|
return var
|
||||||
|
.split(",")
|
||||||
|
.map(|s| s.parse::<u64>()
|
||||||
|
.expect(format!("Failed to parse {}. Invalid syntax.", name).as_str()))
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
use serde_json::Value;
|
|
||||||
use tokio::sync::Mutex;
|
|
||||||
|
|
||||||
use crate::Error;
|
|
||||||
|
|
||||||
pub async fn get_json_mutex(data: &Mutex<Option<Value>>) -> Result<Value, Error> {
|
|
||||||
let data_lock = data.lock().await;
|
|
||||||
return match data_lock.as_ref() {
|
|
||||||
Some(data) => Ok(data.clone()),
|
|
||||||
None => Err("Cannot get mutex data: The data is corrupted!".into()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
pub async fn get_toml_mutex(data: &Mutex<Option<toml::Value>>) -> Result<toml::Value, Error> {
|
|
||||||
let data_lock = data.lock().await;
|
|
||||||
return match data_lock.as_ref() {
|
|
||||||
Some(data) => Ok(data.clone()),
|
|
||||||
None => Err("Cannot get mutex data: The data is corrupted!".into()),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
+6
-7
@@ -2,7 +2,7 @@ use std::{fs, io::Write, path::Path};
|
|||||||
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::{Data, rs_println, rs_warnln, websocket::send_cmd_json};
|
use crate::{rs_println, rs_warnln, websocket::send_cmd_json};
|
||||||
|
|
||||||
|
|
||||||
static DATA_PATH: &str = "./data/db/re_data.json";
|
static DATA_PATH: &str = "./data/db/re_data.json";
|
||||||
@@ -11,7 +11,7 @@ static PRESET_PATH: &str = "./data/defaults/re_data_preset.json";
|
|||||||
pub static POSTS_KEY: &str = "posts";
|
pub static POSTS_KEY: &str = "posts";
|
||||||
|
|
||||||
|
|
||||||
pub async fn read_data(data: &Data, wipe: bool) {
|
pub async fn read_data(wipe: bool) -> Value {
|
||||||
if !Path::new(DATA_PATH).exists() || wipe {
|
if !Path::new(DATA_PATH).exists() || wipe {
|
||||||
rs_println!(
|
rs_println!(
|
||||||
"{} creating new from preset...",
|
"{} creating new from preset...",
|
||||||
@@ -21,9 +21,8 @@ pub async fn read_data(data: &Data, wipe: bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let str_data = fs::read_to_string(DATA_PATH).unwrap();
|
let str_data = fs::read_to_string(DATA_PATH).unwrap();
|
||||||
let json_data: Option<Value> = serde_json::from_str(&str_data).unwrap();
|
let json_data: Value = serde_json::from_str(&str_data).unwrap();
|
||||||
let mut re_data = data.reddit_data.lock().await;
|
return json_data;
|
||||||
*re_data = json_data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -45,9 +44,9 @@ fn generate_data() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn update_data(data: &Data) {
|
pub async fn update_data() {
|
||||||
send_cmd_json("update_data_file", None, true).await;
|
send_cmd_json("update_data_file", None, true).await;
|
||||||
read_data(data, false).await;
|
read_data(false).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,3 +28,17 @@ pub struct Args {
|
|||||||
#[arg(long, help = "Makes the program not use the schedule system.")]
|
#[arg(long, help = "Makes the program not use the schedule system.")]
|
||||||
pub nosched: bool
|
pub nosched: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl Args {
|
||||||
|
pub fn new() -> Self
|
||||||
|
{ return <Args as clap::Parser>::parse(); }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ToString for Args {
|
||||||
|
fn to_string(&self) -> String {
|
||||||
|
return serde_json::to_string(self)
|
||||||
|
.unwrap_or("[FAILED TO CONVERT TO STRING]".to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
+12
-14
@@ -1,4 +1,3 @@
|
|||||||
use crate::db::generic::{get_json_mutex, get_toml_mutex};
|
|
||||||
use crate::db::reddit::update_data;
|
use crate::db::reddit::update_data;
|
||||||
use crate::r#gen::set_status;
|
use crate::r#gen::set_status;
|
||||||
use crate::messages::{make_post_embed, make_removed_embed, EmbedOptions};
|
use crate::messages::{make_post_embed, make_removed_embed, EmbedOptions};
|
||||||
@@ -41,9 +40,7 @@ async fn on_ready(ctx: &serenity::Context, data_about_bot: &Ready, data: &Data)
|
|||||||
data_about_bot.user.id
|
data_about_bot.user.id
|
||||||
);
|
);
|
||||||
|
|
||||||
let m_data = get_toml_mutex(&data.cfg).await.unwrap();
|
set_status(data.cfg.clone(), ctx).await;
|
||||||
|
|
||||||
set_status(m_data, ctx).await;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -88,9 +85,9 @@ async fn approve_btn(ctx: &serenity::Context, data: &Data, c_member: &Member, co
|
|||||||
let c_id = component.channel_id;
|
let c_id = component.channel_id;
|
||||||
let m_id = component.message.id;
|
let m_id = component.message.id;
|
||||||
|
|
||||||
update_data(data).await;
|
update_data().await;
|
||||||
let new_data = &get_json_mutex(&data.reddit_data)
|
let new_data = &data.reddit_data
|
||||||
.await.unwrap()[POSTS_KEY][&url];
|
.lock().await[POSTS_KEY][&url];
|
||||||
|
|
||||||
update_embed(ctx, &url, new_data, &c_id, &m_id).await;
|
update_embed(ctx, &url, new_data, &c_id, &m_id).await;
|
||||||
|
|
||||||
@@ -123,9 +120,9 @@ async fn remove_btn(ctx: &serenity::Context, data: &Data, c_member: &Member, com
|
|||||||
let c_id = component.channel_id;
|
let c_id = component.channel_id;
|
||||||
let m_id = component.message.id;
|
let m_id = component.message.id;
|
||||||
|
|
||||||
update_data(data).await;
|
update_data().await;
|
||||||
let new_data = &get_json_mutex(&data.reddit_data)
|
let new_data = &data.reddit_data
|
||||||
.await.unwrap()[POSTS_KEY][&url];
|
.lock().await[POSTS_KEY][&url];
|
||||||
|
|
||||||
update_embed(ctx, &url, new_data, &c_id, &m_id).await;
|
update_embed(ctx, &url, new_data, &c_id, &m_id).await;
|
||||||
|
|
||||||
@@ -144,16 +141,17 @@ async fn remove_btn(ctx: &serenity::Context, data: &Data, c_member: &Member, com
|
|||||||
|
|
||||||
async fn vote_btn(ctx: &serenity::Context, data: &Data, c_member: &Member, component: &ComponentInteraction, url: String, vote: bool) -> Result<(), Error> {
|
async fn vote_btn(ctx: &serenity::Context, data: &Data, c_member: &Member, component: &ComponentInteraction, url: String, vote: bool) -> Result<(), Error> {
|
||||||
let uid: u64 = c_member.user.id.into();
|
let uid: u64 = c_member.user.id.into();
|
||||||
let is_mod = is_bk_mod(data.bk_mods.clone(), uid);
|
let is_mod = is_bk_mod(data.env_vars.reddit_mod_discord_ids.clone(), uid);
|
||||||
|
|
||||||
let r = send_cmd_json("set_vote_post", Some(json!([&url, uid, is_mod, true, !vote])), true).await.unwrap();
|
let r = send_cmd_json("set_vote_post", Some(json!([&url, uid, is_mod, true, !vote])), true).await.unwrap();
|
||||||
|
|
||||||
let c_id = component.channel_id;
|
let c_id = component.channel_id;
|
||||||
let m_id = component.message.id;
|
let m_id = component.message.id;
|
||||||
|
|
||||||
update_data(data).await;
|
update_data().await;
|
||||||
let new_data = &get_json_mutex(&data.reddit_data)
|
let new_data = &data.reddit_data
|
||||||
.await.unwrap()[POSTS_KEY][&url];
|
.lock().await[POSTS_KEY][&url];
|
||||||
|
|
||||||
update_embed(ctx, &url, new_data, &c_id, &m_id).await;
|
update_embed(ctx, &url, new_data, &c_id, &m_id).await;
|
||||||
|
|
||||||
if r["value"].as_bool().unwrap() {
|
if r["value"].as_bool().unwrap() {
|
||||||
|
|||||||
+23
-34
@@ -6,51 +6,41 @@ use poise::serenity_prelude::Client;
|
|||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use toml::Value;
|
use toml::Value;
|
||||||
|
|
||||||
|
use crate::db::env_vars::AssistantEnv;
|
||||||
use crate::db::{cfg, discord, reddit};
|
use crate::db::{cfg, discord, reddit};
|
||||||
use crate::db::generic::get_toml_mutex;
|
|
||||||
use crate::games::wwrps::RPSGame;
|
use crate::games::wwrps::RPSGame;
|
||||||
use crate::lang::Lang;
|
use crate::lang::Lang;
|
||||||
use crate::{Args, Cmd, Data, cmds, events, rs_println};
|
use crate::{Args, Cmd, Data, cmds, events, rs_println};
|
||||||
|
|
||||||
|
|
||||||
pub async fn gen_data(args: Args, owners: Vec<u64>) -> Data {
|
pub async fn gen_data(args: Args, env_vars: AssistantEnv) -> Data {
|
||||||
let ball_classic_str = std::fs::read_to_string("./cfg/8-ball_classic.txt").unwrap();
|
let ball_classic_str = std::fs::read_to_string("./cfg/8-ball_classic.txt").unwrap();
|
||||||
let ball_quirk_str = std::fs::read_to_string("./cfg/8-ball_quirky.txt").unwrap();
|
let ball_quirk_str = std::fs::read_to_string("./cfg/8-ball_quirky.txt").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 mods_env = std::env::var("ASSISTANT_BK_MODS").unwrap_or("0".to_string());
|
let re_data = reddit:: read_data(args.clone().wipe).await;
|
||||||
let mods_vec_str: Vec<String> = mods_env.split(",").map(String::from).collect();
|
let dc_data = discord::read_data(args.clone().wipe).await;
|
||||||
let mods_vec_u64: Vec<u64> = mods_vec_str
|
let cf_data = cfg:: read_data(args.clone().wipe).await;
|
||||||
.iter()
|
|
||||||
.map(|s| s.parse::<u64>().expect("Failed to parse ASSISTANT_BK_MODS. Invalid syntax."))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let data = Data {
|
return Data {
|
||||||
owners,
|
|
||||||
ball_prompts: [ball_classic, ball_quirk],
|
|
||||||
rps_game: Mutex::new(RPSGame::new()),
|
|
||||||
bk_mods: mods_vec_u64,
|
|
||||||
reddit_data: None.into(),
|
|
||||||
discord_data: None.into(),
|
|
||||||
cfg: None.into(),
|
|
||||||
args: args.clone(),
|
args: args.clone(),
|
||||||
|
ball_prompts: [ball_classic, ball_quirk],
|
||||||
|
cfg: cf_data,
|
||||||
|
discord_data: dc_data.into(),
|
||||||
|
env_vars: env_vars,
|
||||||
lang_name: "".to_string().into(),
|
lang_name: "".to_string().into(),
|
||||||
lang: Lang::new().into()
|
lang: Lang::new().into(),
|
||||||
|
reddit_data: re_data.into(),
|
||||||
|
rps_game: Mutex::new(RPSGame::new())
|
||||||
};
|
};
|
||||||
|
|
||||||
discord::read_data(&data, args.clone().wipe).await;
|
|
||||||
reddit:: read_data(&data, args.clone().wipe).await;
|
|
||||||
cfg:: read_data(&data, args.clone().wipe).await;
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn gen_bot(data: Data, args: Args) -> Client {
|
pub async fn gen_bot(data: Data) -> Client {
|
||||||
let token =
|
let token =
|
||||||
if !args.test { std::env::var("ASSISTANT_TOKEN").expect("Missing ASSISTANT_TOKEN env var!") }
|
if !data.args.test { std::env::var("ASSISTANT_TOKEN").expect("Missing ASSISTANT_TOKEN env var!") }
|
||||||
else { std::env::var("ASSISTANT_TOKEN_TEST").expect("Missing ASSISTANT_TOKEN_TEST env var!") };
|
else { std::env::var("ASSISTANT_TOKEN_TEST").expect("Missing ASSISTANT_TOKEN_TEST env var!") };
|
||||||
|
|
||||||
let intents = serenity::GatewayIntents::all();
|
let intents = serenity::GatewayIntents::all();
|
||||||
@@ -60,7 +50,7 @@ pub async fn gen_bot(data: Data, args: Args) -> Client {
|
|||||||
let token_end_len = token[peek_len..].len();
|
let token_end_len = token[peek_len..].len();
|
||||||
rs_println!("Token: {}{}", token_peek, "*".repeat(token_end_len));
|
rs_println!("Token: {}{}", token_peek, "*".repeat(token_end_len));
|
||||||
|
|
||||||
let own: HashSet<UserId> = data.owners
|
let owner_users: HashSet<UserId> = data.env_vars.bot_owners
|
||||||
.clone()
|
.clone()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter_map(|i| if i == 0 { None } else { Some(UserId::from(i))})
|
.filter_map(|i| if i == 0 { None } else { Some(UserId::from(i))})
|
||||||
@@ -68,7 +58,7 @@ pub async fn gen_bot(data: Data, args: Args) -> Client {
|
|||||||
|
|
||||||
let framework = poise::Framework::builder()
|
let framework = poise::Framework::builder()
|
||||||
.options(poise::FrameworkOptions {
|
.options(poise::FrameworkOptions {
|
||||||
owners: own,
|
owners: owner_users,
|
||||||
commands: make_cmd_vec(&data).await,
|
commands: make_cmd_vec(&data).await,
|
||||||
event_handler: events::event_handler,
|
event_handler: events::event_handler,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
@@ -89,7 +79,7 @@ pub async fn gen_bot(data: Data, args: Args) -> Client {
|
|||||||
|
|
||||||
|
|
||||||
async fn make_cmd_vec(data: &Data) -> Vec<Cmd> {
|
async fn make_cmd_vec(data: &Data) -> Vec<Cmd> {
|
||||||
let mut cmds = vec![
|
let mut cmds: Vec<Cmd> = vec![
|
||||||
// GENERIC
|
// GENERIC
|
||||||
cmds::generic::help::cmd(),
|
cmds::generic::help::cmd(),
|
||||||
cmds::generic::eight_ball::cmd(),
|
cmds::generic::eight_ball::cmd(),
|
||||||
@@ -110,9 +100,8 @@ async fn make_cmd_vec(data: &Data) -> Vec<Cmd> {
|
|||||||
// DATABASE
|
// DATABASE
|
||||||
cmds::db::main_cmd::cmd()
|
cmds::db::main_cmd::cmd()
|
||||||
];
|
];
|
||||||
let cfg = get_toml_mutex(&data.cfg).await.unwrap();
|
|
||||||
|
|
||||||
let disabled = cfg["commands"]["disabled_categories"]
|
let disabled = data.cfg["commands"]["disabled_categories"]
|
||||||
.as_array()
|
.as_array()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
@@ -125,12 +114,12 @@ async fn make_cmd_vec(data: &Data) -> Vec<Cmd> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn set_status(m_data: Value, ctx: &serenity::Context) {
|
pub async fn set_status(cfg: Value, ctx: &serenity::Context) {
|
||||||
let status_str: String;
|
let status_str: String;
|
||||||
|
|
||||||
let status = m_data["general"]["status"].as_str().unwrap();
|
let status = cfg["general"]["status"].as_str().unwrap();
|
||||||
let status_c = m_data["general"]["statusCommitNumber"].as_bool().unwrap();
|
let status_c = cfg["general"]["statusCommitNumber"].as_bool().unwrap();
|
||||||
let status_ec = m_data["general"]["statusExperimentalCommit"].as_bool().unwrap();
|
let status_ec = cfg["general"]["statusExperimentalCommit"].as_bool().unwrap();
|
||||||
|
|
||||||
if status_c {
|
if status_c {
|
||||||
let commit_num_r = process::Command::new("git")
|
let commit_num_r = process::Command::new("git")
|
||||||
|
|||||||
+7
-4
@@ -66,7 +66,7 @@ macro_rules! warnln {
|
|||||||
macro_rules! lang {
|
macro_rules! lang {
|
||||||
($key:expr) => {
|
($key:expr) => {
|
||||||
{
|
{
|
||||||
use $crate::{LANG, errln};
|
/*use $crate::{LANG, errln};
|
||||||
let value = unsafe {
|
let value = unsafe {
|
||||||
LANG
|
LANG
|
||||||
.as_ref()
|
.as_ref()
|
||||||
@@ -76,11 +76,13 @@ macro_rules! lang {
|
|||||||
|
|
||||||
if value.is_none() { errln!("Key not found in LANG JSON: \"{}\"", $key); }
|
if value.is_none() { errln!("Key not found in LANG JSON: \"{}\"", $key); }
|
||||||
|
|
||||||
value.unwrap().as_str().expect("LANG JSON value is not a string!").to_string()
|
value.unwrap().as_str().expect("LANG JSON value is not a string!").to_string()*/
|
||||||
|
|
||||||
|
"hello".to_string()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
($key:expr, $($arg:expr),*) => {{
|
($key:expr, $($arg:expr),*) => {{
|
||||||
use $crate::{LANG, errln};
|
/*use $crate::{LANG, errln};
|
||||||
use formatx::formatx;
|
use formatx::formatx;
|
||||||
|
|
||||||
let value = unsafe {
|
let value = unsafe {
|
||||||
@@ -93,6 +95,7 @@ macro_rules! lang {
|
|||||||
if value.is_none() { errln!("Key not found in LANG JSON: \"{}\"", $key); }
|
if value.is_none() { errln!("Key not found in LANG JSON: \"{}\"", $key); }
|
||||||
|
|
||||||
let format_str = value.unwrap().as_str().expect("LANG JSON value is not a string!");
|
let format_str = value.unwrap().as_str().expect("LANG JSON value is not a string!");
|
||||||
formatx!(format_str, $($arg),*).unwrap()
|
formatx!(format_str, $($arg),*).unwrap()*/
|
||||||
|
"hello".to_string()
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
+74
-57
@@ -1,24 +1,22 @@
|
|||||||
#![warn(unused_extern_crates)]
|
|
||||||
#![allow(clippy::needless_return)]
|
#![allow(clippy::needless_return)]
|
||||||
#![allow(static_mut_refs)]
|
|
||||||
|
|
||||||
|
|
||||||
mod events;
|
|
||||||
mod messages;
|
|
||||||
mod python;
|
|
||||||
mod macros;
|
|
||||||
#[allow(unknown_lints)]
|
|
||||||
mod websocket;
|
|
||||||
mod cmds;
|
mod cmds;
|
||||||
mod db;
|
mod db;
|
||||||
|
mod events;
|
||||||
mod games;
|
mod games;
|
||||||
mod schedule;
|
|
||||||
mod gen;
|
mod gen;
|
||||||
mod lang;
|
mod lang;
|
||||||
|
mod macros;
|
||||||
|
mod messages;
|
||||||
|
mod python;
|
||||||
|
mod schedule;
|
||||||
|
mod websocket;
|
||||||
|
|
||||||
|
|
||||||
use std::process;
|
use std::process;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
use std::thread::JoinHandle;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use std::error::Error as StdErr;
|
use std::error::Error as StdErr;
|
||||||
@@ -31,8 +29,8 @@ use tokio::runtime::Runtime;
|
|||||||
use websocket::send_cmd_json;
|
use websocket::send_cmd_json;
|
||||||
|
|
||||||
use crate::db::bot_data::Data;
|
use crate::db::bot_data::Data;
|
||||||
|
use crate::db::env_vars::AssistantEnv;
|
||||||
use crate::db::terminal_args::Args;
|
use crate::db::terminal_args::Args;
|
||||||
use crate::db::generic::get_toml_mutex;
|
|
||||||
use crate::schedule::Schedule;
|
use crate::schedule::Schedule;
|
||||||
|
|
||||||
|
|
||||||
@@ -43,79 +41,98 @@ type Cmd = Command<Data, Box<dyn StdErr + Send + Sync>>;
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let args = <Args as clap::Parser>::parse();
|
let args = Args::new();
|
||||||
let args_str = serde_json::to_string(&args).expect("Error serializing args to JSON");
|
rs_println!("ARGS: {}", args.to_string());
|
||||||
|
let env_vars = AssistantEnv::new(args.test);
|
||||||
let own_env = std::env::var("ASSISTANT_OWNERS").unwrap_or("0".to_string());
|
|
||||||
let own_vec_str: Vec<String> = own_env.split(",").map(String::from).collect();
|
|
||||||
let own_vec_u64: Vec<u64> = own_vec_str
|
|
||||||
.iter()
|
|
||||||
.map(|s| s.parse::<u64>().expect("Failed to parse ASSISTANT_OWNERS. Invalid syntax."))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
rs_println!("Generating and/or fetching data and config...");
|
rs_println!("Generating and/or fetching data and config...");
|
||||||
let data = gen_data(args.clone(), own_vec_u64.clone()).await;
|
let data = gen_data(args, env_vars).await;
|
||||||
|
|
||||||
rs_println!("[IMPORTANT] The below message is a test message, it should be written in the language you've selected\nTest message: {}", lang!("log_lang_load_success"));
|
rs_println!("[IMPORTANT] The below message is a test message, it should be written in the language you've selected\nTest message: {}", lang!("log_lang_load_success"));
|
||||||
|
|
||||||
if args.py && !args.rs {
|
// We start this here cuz we have all the data that we need
|
||||||
let _ = python::start(args, *data.lang_name.lock().await).await;
|
if data.args.py && !data.args.rs {
|
||||||
|
let _ = python::start(
|
||||||
|
data.args.clone(),
|
||||||
|
data.lang_name.clone(),
|
||||||
|
data.env_vars.clone(),
|
||||||
|
).await;
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
else if args.rs && ! args.py {
|
else if data.args.rs && ! data.args.py {
|
||||||
start(args, data).await;
|
start_bot(data).await;
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
rs_println!("ARGS: {}", args_str);
|
let cfg_arr = data.cfg["commands"]["disabled_categories"].as_array().unwrap();
|
||||||
|
|
||||||
let cfg = get_toml_mutex(&data.cfg).await.unwrap();
|
|
||||||
let cfg_arr = cfg["commands"]["disabled_categories"].as_array().unwrap();
|
|
||||||
let run_py = !cfg_arr.iter().any(|val| val.as_str() == Some("re"));
|
let run_py = !cfg_arr.iter().any(|val| val.as_str() == Some("re"));
|
||||||
|
|
||||||
let rt_rs = Runtime::new().unwrap();
|
|
||||||
let rt_py = Runtime::new().unwrap();
|
|
||||||
let python_args = args.clone();
|
|
||||||
let rust_args = args.clone();
|
|
||||||
|
|
||||||
if !run_py { rs_println!("[IMPORTANT] You have disabled the \"re\" commands in the CFG. The app will not run the Python code and the websockets to save resources!"); }
|
if !run_py { rs_println!("[IMPORTANT] You have disabled the \"re\" commands in the CFG. The app will not run the Python code and the websockets to save resources!"); }
|
||||||
|
|
||||||
let rust = thread::spawn(move || {
|
if !data.args.nosched { start_schedules(data.args.test); }
|
||||||
rt_rs.block_on(async {
|
|
||||||
if run_py { websocket::start(rust_args.clone(), own_vec_u64.clone()).await; }
|
let python = start_py(
|
||||||
start(rust_args, data).await;
|
data.args.clone(),
|
||||||
});
|
data.lang_name.clone(),
|
||||||
});
|
data.env_vars.clone(),
|
||||||
|
run_py
|
||||||
let python = thread::spawn(move || {
|
);
|
||||||
rt_py.block_on(async {
|
let rust = start_rs(data, run_py);
|
||||||
if run_py { let _ = python::start(python_args, *data.lang_name.lock().await).await; }
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
if !args.nosched {
|
|
||||||
let dur = if args.test { Duration::from_secs(60) } else { Duration::from_secs(60 * 10) };
|
|
||||||
|
|
||||||
let schedules: Vec<Schedule> = vec![
|
|
||||||
(dur, || Box::pin(read_reddit_inbox()))
|
|
||||||
];
|
|
||||||
|
|
||||||
run_schedules(schedules).await;
|
|
||||||
}
|
|
||||||
|
|
||||||
rust.join().unwrap();
|
rust.join().unwrap();
|
||||||
python.join().unwrap();
|
python.join().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn start(args: Args, data: Data) {
|
|
||||||
let mut bot = gen_bot(data, args).await;
|
fn start_rs(data: Data, run_py: bool) -> JoinHandle<()> {
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
|
||||||
|
return thread::spawn(move || {
|
||||||
|
rt.block_on(async {
|
||||||
|
if run_py { websocket::start(&data).await; }
|
||||||
|
start_bot(data).await;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn start_py(
|
||||||
|
args: Args,
|
||||||
|
lang_name: String,
|
||||||
|
env_vars: AssistantEnv,
|
||||||
|
run_py: bool
|
||||||
|
) -> JoinHandle<()> {
|
||||||
|
let rt = Runtime::new().unwrap();
|
||||||
|
|
||||||
|
return thread::spawn(move || {
|
||||||
|
rt.block_on(async {
|
||||||
|
if run_py { let _ = python::start(args, lang_name, env_vars).await; }
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn start_bot(data: Data) {
|
||||||
|
let mut bot = gen_bot(data).await;
|
||||||
|
|
||||||
rs_println!("Starting Discord bot...");
|
rs_println!("Starting Discord bot...");
|
||||||
bot.start().await.unwrap();
|
bot.start().await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async fn start_schedules(test: bool) {
|
||||||
|
let dur = if test { Duration::from_secs(60) }
|
||||||
|
else { Duration::from_secs(60 * 10) };
|
||||||
|
|
||||||
|
let schedules: Vec<Schedule> = vec![
|
||||||
|
(dur, || Box::pin(read_reddit_inbox()))
|
||||||
|
];
|
||||||
|
|
||||||
|
run_schedules(schedules).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn read_reddit_inbox() {
|
async fn read_reddit_inbox() {
|
||||||
unsafe {
|
unsafe {
|
||||||
if !websocket::HAS_CONNECTED { return; }
|
if !websocket::HAS_CONNECTED { return; }
|
||||||
|
|||||||
+21
-9
@@ -1,7 +1,7 @@
|
|||||||
use std::env;
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
|
||||||
use crate::{lang, Args, Context};
|
use crate::db::bot_data::Data;
|
||||||
|
use crate::{lang, Context};
|
||||||
|
|
||||||
use base64::engine::general_purpose;
|
use base64::engine::general_purpose;
|
||||||
use base64::Engine;
|
use base64::Engine;
|
||||||
@@ -199,16 +199,26 @@ pub async fn http_edit_msg(
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn send_dm(msg: String, args: Args, receivers: Vec<u64>) {
|
pub async fn send_dm(msg: String, data: &Data) {
|
||||||
let token: String =
|
let http = Http::new(&data.env_vars.token);
|
||||||
if !args.test { env::var("ASSISTANT_TOKEN") .expect("Missing ASSISTANT_TOKEN env var!") }
|
|
||||||
else { env::var("ASSISTANT_TOKEN_TEST").expect("Missing ASSISTANT_TOKEN_TEST env var!") };
|
|
||||||
|
|
||||||
|
let c_msg = CreateMessage::new().content(msg);
|
||||||
|
|
||||||
|
for uid in data.env_vars.bot_owners.clone() {
|
||||||
|
if uid == 0 { continue; }
|
||||||
|
let user = UserId::new(uid);
|
||||||
|
let _ = user.dm(http.as_ref(), c_msg.clone()).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn send_dm_min(msg: String, token: String, bot_owners: Vec<u64>) {
|
||||||
let http = Http::new(&token);
|
let http = Http::new(&token);
|
||||||
|
|
||||||
let c_msg = CreateMessage::new().content(msg);
|
let c_msg = CreateMessage::new().content(msg);
|
||||||
|
|
||||||
for uid in receivers {
|
for uid in bot_owners {
|
||||||
if uid == 0 { continue; }
|
if uid == 0 { continue; }
|
||||||
let user = UserId::new(uid);
|
let user = UserId::new(uid);
|
||||||
let _ = user.dm(http.as_ref(), c_msg.clone()).await;
|
let _ = user.dm(http.as_ref(), c_msg.clone()).await;
|
||||||
@@ -265,9 +275,11 @@ pub fn make_removed_embed(post_data: &Value, url: &str, ephemeral: bool) -> Embe
|
|||||||
|
|
||||||
let desc = lang!(
|
let desc = lang!(
|
||||||
"dc_msg_embed_re_removed",
|
"dc_msg_embed_re_removed",
|
||||||
if !post_data["removed"]["by"].is_null() { post_data["removed"]["by"].as_str().unwrap() }
|
if !post_data["removed"]["by"].is_null()
|
||||||
|
{ post_data["removed"]["by"].as_str().unwrap() }
|
||||||
else { &none },
|
else { &none },
|
||||||
if !post_data["removed"]["reason"].is_null() { post_data["removed"]["reason"].as_str().unwrap() }
|
if !post_data["removed"]["reason"].is_null()
|
||||||
|
{ post_data["removed"]["reason"].as_str().unwrap() }
|
||||||
else { &none }
|
else { &none }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
+15
-24
@@ -1,5 +1,7 @@
|
|||||||
use crate::messages::send_dm;
|
use crate::db::env_vars::AssistantEnv;
|
||||||
use crate::{errln, lang, rs_println, Args};
|
use crate::db::terminal_args::Args;
|
||||||
|
use crate::messages::send_dm_min;
|
||||||
|
use crate::{errln, lang, rs_println};
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
@@ -9,7 +11,7 @@ use pyo3::prelude::*;
|
|||||||
use pyo3::types::PyList;
|
use pyo3::types::PyList;
|
||||||
|
|
||||||
|
|
||||||
pub async fn start(args: Args, lang_name: String) -> PyResult<()> {
|
pub async fn start(args: Args, lang_name: String, env_vars: AssistantEnv) -> PyResult<()> {
|
||||||
rs_println!("Running Python program...");
|
rs_println!("Running Python program...");
|
||||||
|
|
||||||
let args_str = serde_json::to_string(&args).expect("Error serializing args to JSON");
|
let args_str = serde_json::to_string(&args).expect("Error serializing args to JSON");
|
||||||
@@ -23,15 +25,12 @@ pub async fn start(args: Args, lang_name: String) -> PyResult<()> {
|
|||||||
let py_args = args_str.replace(":true", ":True").replace(":false", ":False");
|
let py_args = args_str.replace(":true", ":True").replace(":false", ":False");
|
||||||
let app_path: CString;
|
let app_path: CString;
|
||||||
|
|
||||||
unsafe {
|
app_path = CString::new(format!(
|
||||||
app_path = CString::new(
|
"args = {}\nlang_name = \"{}\"\n{}",
|
||||||
format!("args = {}\nlang_name = \"{}\"\n{}",
|
py_args,
|
||||||
py_args,
|
lang_name,
|
||||||
lang_name.clone(),
|
code
|
||||||
code
|
)).unwrap();
|
||||||
)
|
|
||||||
).unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut traceback: String = String::new();
|
let mut traceback: String = String::new();
|
||||||
let mut is_error = false;
|
let mut is_error = false;
|
||||||
@@ -57,19 +56,11 @@ pub async fn start(args: Args, lang_name: String) -> PyResult<()> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
if is_error {
|
if is_error {
|
||||||
let own_env = std::env::var("ASSISTANT_OWNERS").unwrap_or("0".to_string());
|
send_dm_min(
|
||||||
let own_vec_str: Vec<String> = own_env.split(",").map(String::from).collect();
|
lang!("dc_msg_dm_python_err", traceback),
|
||||||
let own_vec_u64: Vec<u64> = own_vec_str
|
env_vars.token.clone(),
|
||||||
.iter()
|
env_vars.bot_owners.clone()
|
||||||
.map(|s| s.parse::<u64>().expect("Failed to parse ASSISTANT_OWNERS. Invalid syntax."))
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
send_dm(
|
|
||||||
lang!("dc_msg_dm_python_err", format!("{}", traceback)),
|
|
||||||
args,
|
|
||||||
own_vec_u64
|
|
||||||
).await;
|
).await;
|
||||||
|
|
||||||
errln!("pyO3: {}", traceback);
|
errln!("pyO3: {}", traceback);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-21
@@ -8,7 +8,8 @@ use futures::StreamExt;
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use serde_json::{Value, json};
|
use serde_json::{Value, json};
|
||||||
|
|
||||||
use crate::messages::send_dm;
|
use crate::db::bot_data::Data;
|
||||||
|
use crate::messages::send_dm_min;
|
||||||
use crate::{lang, rs_println};
|
use crate::{lang, rs_println};
|
||||||
use crate::Args;
|
use crate::Args;
|
||||||
|
|
||||||
@@ -103,17 +104,25 @@ async fn receive_response() -> Option<Value> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub async fn start(args: Args, owners: Vec<u64>) {
|
pub async fn start(data: &Data) {
|
||||||
rs_println!("Running local websocket...");
|
rs_println!("Running local websocket...");
|
||||||
let ip = format!("127.0.0.1:{}", args.port);
|
let ip = format!("127.0.0.1:{}", data.args.port);
|
||||||
let listener = TcpListener::bind(&ip).await.unwrap();
|
let listener = TcpListener::bind(&ip).await.unwrap();
|
||||||
rs_println!("WebSocket server running on ws://{}", ip);
|
rs_println!("WebSocket server running on ws://{}", ip);
|
||||||
|
|
||||||
tokio::spawn(handle_connections(listener, args, owners));
|
tokio::spawn(handle_connections(
|
||||||
|
listener,
|
||||||
|
data.env_vars.token.clone(),
|
||||||
|
data.env_vars.bot_owners.clone()
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn handle_connections(listener: TcpListener, args: Args, owners: Vec<u64>) {
|
async fn handle_connections(
|
||||||
|
listener: TcpListener,
|
||||||
|
token: String,
|
||||||
|
bot_owners: Vec<u64>
|
||||||
|
) {
|
||||||
while let Ok((stream, _)) = listener.accept().await {
|
while let Ok((stream, _)) = listener.accept().await {
|
||||||
let ws_stream = accept_async(stream).await.unwrap();
|
let ws_stream = accept_async(stream).await.unwrap();
|
||||||
let (sender, receiver) = ws_stream.split();
|
let (sender, receiver) = ws_stream.split();
|
||||||
@@ -124,14 +133,17 @@ async fn handle_connections(listener: TcpListener, args: Args, owners: Vec<u64>)
|
|||||||
set_sender(sender_arc.clone()).await;
|
set_sender(sender_arc.clone()).await;
|
||||||
set_receiver(receiver_arc.clone()).await;
|
set_receiver(receiver_arc.clone()).await;
|
||||||
|
|
||||||
while let Some(Ok(msg)) = receiver_arc.lock().await.as_mut().unwrap().next().await {
|
while let Some(Ok(msg)) = receiver_arc.lock().await.as_mut().unwrap().next().await
|
||||||
handle_message(msg, args.clone(), owners.clone()).await;
|
{ handle_message(msg, token.clone(), bot_owners.clone()).await; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn handle_message(msg: tungstenite::protocol::Message, args: Args, owners: Vec<u64>) {
|
async fn handle_message(
|
||||||
|
msg: tungstenite::protocol::Message,
|
||||||
|
token: String,
|
||||||
|
bot_owners: Vec<u64>
|
||||||
|
) {
|
||||||
match msg {
|
match msg {
|
||||||
tungstenite::Message::Text(text) => {
|
tungstenite::Message::Text(text) => {
|
||||||
rs_println!("Received from Python: {}", text);
|
rs_println!("Received from Python: {}", text);
|
||||||
@@ -139,7 +151,11 @@ async fn handle_message(msg: tungstenite::protocol::Message, args: Args, owners:
|
|||||||
if let Some(stripped) = text.strip_prefix("json:") {
|
if let Some(stripped) = text.strip_prefix("json:") {
|
||||||
let t_json: Value = serde_json::from_str(stripped).unwrap();
|
let t_json: Value = serde_json::from_str(stripped).unwrap();
|
||||||
if t_json.get("error").is_some() {
|
if t_json.get("error").is_some() {
|
||||||
send_dm(lang!("dc_msg_dm_python_err_socket"), args, owners).await;
|
send_dm_min(
|
||||||
|
lang!("dc_msg_dm_python_err_socket"),
|
||||||
|
token,
|
||||||
|
bot_owners
|
||||||
|
).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -150,16 +166,7 @@ async fn handle_message(msg: tungstenite::protocol::Message, args: Args, owners:
|
|||||||
HAS_CONNECTED = true;
|
HAS_CONNECTED = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
tungstenite::Message::Binary(bytes) => {
|
_ => {}
|
||||||
if args.dev && args.ping {
|
|
||||||
rs_println!("[Binary] from Python: {:?}", bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
if args.dev && args.ping {
|
|
||||||
rs_println!("Received from Python: [UNKNOWN / OTHER]");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user