removed all guild data related code
This commit is contained in:
		
							
								
								
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
									
									
										generated
									
									
									
								
							@@ -1201,7 +1201,6 @@ dependencies = [
 | 
				
			|||||||
 "base64",
 | 
					 "base64",
 | 
				
			||||||
 "chrono",
 | 
					 "chrono",
 | 
				
			||||||
 "chrono-tz",
 | 
					 "chrono-tz",
 | 
				
			||||||
 "dashmap",
 | 
					 | 
				
			||||||
 "dotenv",
 | 
					 "dotenv",
 | 
				
			||||||
 "env_logger",
 | 
					 "env_logger",
 | 
				
			||||||
 "humantime",
 | 
					 "humantime",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@ authors = ["jellywx <judesouthworth@pm.me>"]
 | 
				
			|||||||
edition = "2018"
 | 
					edition = "2018"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[dependencies]
 | 
					[dependencies]
 | 
				
			||||||
dashmap = "4.0"
 | 
					 | 
				
			||||||
dotenv = "0.15"
 | 
					dotenv = "0.15"
 | 
				
			||||||
humantime = "2.1"
 | 
					humantime = "2.1"
 | 
				
			||||||
tokio = { version = "1", features = ["process", "full"] }
 | 
					tokio = { version = "1", features = ["process", "full"] }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3,7 +3,6 @@ use regex_command_attr::command;
 | 
				
			|||||||
use serenity::{builder::CreateEmbedFooter, client::Context};
 | 
					use serenity::{builder::CreateEmbedFooter, client::Context};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    consts::DEFAULT_PREFIX,
 | 
					 | 
				
			||||||
    framework::{CommandInvoke, CreateGenericResponse},
 | 
					    framework::{CommandInvoke, CreateGenericResponse},
 | 
				
			||||||
    models::CtxData,
 | 
					    models::CtxData,
 | 
				
			||||||
    THEME_COLOR,
 | 
					    THEME_COLOR,
 | 
				
			||||||
@@ -28,8 +27,6 @@ fn footer(ctx: &Context) -> impl FnOnce(&mut CreateEmbedFooter) -> &mut CreateEm
 | 
				
			|||||||
#[description("Get information about the bot")]
 | 
					#[description("Get information about the bot")]
 | 
				
			||||||
#[group("Info")]
 | 
					#[group("Info")]
 | 
				
			||||||
async fn info(ctx: &Context, invoke: &mut CommandInvoke) {
 | 
					async fn info(ctx: &Context, invoke: &mut CommandInvoke) {
 | 
				
			||||||
    let prefix = ctx.prefix(invoke.guild_id()).await;
 | 
					 | 
				
			||||||
    let current_user = ctx.cache.current_user();
 | 
					 | 
				
			||||||
    let footer = footer(ctx);
 | 
					    let footer = footer(ctx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let _ = invoke
 | 
					    let _ = invoke
 | 
				
			||||||
@@ -38,18 +35,15 @@ async fn info(ctx: &Context, invoke: &mut CommandInvoke) {
 | 
				
			|||||||
            CreateGenericResponse::new().embed(|e| {
 | 
					            CreateGenericResponse::new().embed(|e| {
 | 
				
			||||||
                e.title("Info")
 | 
					                e.title("Info")
 | 
				
			||||||
                    .description(format!(
 | 
					                    .description(format!(
 | 
				
			||||||
                        "Default prefix: `{default_prefix}`
 | 
					                        "Help: `/help`
 | 
				
			||||||
Reset prefix: `@{user} prefix {default_prefix}`
 | 
					
 | 
				
			||||||
Help: `{prefix}help`**Welcome to Reminder Bot!**
 | 
					**Welcome to Reminder Bot!**
 | 
				
			||||||
Developer: <@203532103185465344>
 | 
					Developer: <@203532103185465344>
 | 
				
			||||||
Icon: <@253202252821430272>
 | 
					Icon: <@253202252821430272>
 | 
				
			||||||
Find me on https://discord.jellywx.com and on https://github.com/JellyWX :)
 | 
					Find me on https://discord.jellywx.com and on https://github.com/JellyWX :)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Invite the bot: https://invite.reminder-bot.com/
 | 
					Invite the bot: https://invite.reminder-bot.com/
 | 
				
			||||||
Use our dashboard: https://reminder-bot.com/",
 | 
					Use our dashboard: https://reminder-bot.com/",
 | 
				
			||||||
                        default_prefix = *DEFAULT_PREFIX,
 | 
					 | 
				
			||||||
                        user = current_user.name,
 | 
					 | 
				
			||||||
                        prefix = prefix
 | 
					 | 
				
			||||||
                    ))
 | 
					                    ))
 | 
				
			||||||
                    .footer(footer)
 | 
					                    .footer(footer)
 | 
				
			||||||
                    .color(*THEME_COLOR)
 | 
					                    .color(*THEME_COLOR)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@ use crate::{
 | 
				
			|||||||
    consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
 | 
					    consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
 | 
				
			||||||
    framework::{CommandInvoke, CommandOptions, CreateGenericResponse, OptionValue},
 | 
					    framework::{CommandInvoke, CommandOptions, CreateGenericResponse, OptionValue},
 | 
				
			||||||
    hooks::{CHECK_GUILD_PERMISSIONS_HOOK, CHECK_MANAGED_PERMISSIONS_HOOK},
 | 
					    hooks::{CHECK_GUILD_PERMISSIONS_HOOK, CHECK_MANAGED_PERMISSIONS_HOOK},
 | 
				
			||||||
    models::{channel_data::ChannelData, command_macro::CommandMacro, CtxData},
 | 
					    models::{command_macro::CommandMacro, CtxData},
 | 
				
			||||||
    PopularTimezones, RecordingMacros, RegexFramework, SQLPool,
 | 
					    PopularTimezones, RecordingMacros, RegexFramework, SQLPool,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,6 @@ use regex_command_attr::command;
 | 
				
			|||||||
use serenity::{builder::CreateEmbed, client::Context, model::channel::Channel};
 | 
					use serenity::{builder::CreateEmbed, client::Context, model::channel::Channel};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    check_subscription_on_message,
 | 
					 | 
				
			||||||
    component_models::{
 | 
					    component_models::{
 | 
				
			||||||
        pager::{DelPager, LookPager, Pager},
 | 
					        pager::{DelPager, LookPager, Pager},
 | 
				
			||||||
        ComponentDataModel, DelSelector,
 | 
					        ComponentDataModel, DelSelector,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,7 +10,7 @@ const THEME_COLOR_FALLBACK: u32 = 0x8fb677;
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use std::{collections::HashSet, env, iter::FromIterator};
 | 
					use std::{collections::HashSet, env, iter::FromIterator};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use regex::{Regex, RegexBuilder};
 | 
					use regex::Regex;
 | 
				
			||||||
use serenity::http::AttachmentType;
 | 
					use serenity::http::AttachmentType;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
lazy_static! {
 | 
					lazy_static! {
 | 
				
			||||||
@@ -23,29 +23,9 @@ lazy_static! {
 | 
				
			|||||||
        env!("WEBHOOK_AVATAR"),
 | 
					        env!("WEBHOOK_AVATAR"),
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
        .into();
 | 
					        .into();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref REGEX_CHANNEL: Regex = Regex::new(r#"^\s*<#(\d+)>\s*$"#).unwrap();
 | 
					    pub static ref REGEX_CHANNEL: Regex = Regex::new(r#"^\s*<#(\d+)>\s*$"#).unwrap();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref REGEX_ROLE: Regex = Regex::new(r#"<@&(\d+)>"#).unwrap();
 | 
					    pub static ref REGEX_ROLE: Regex = Regex::new(r#"<@&(\d+)>"#).unwrap();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref REGEX_CONTENT_SUBSTITUTION: Regex = Regex::new(r#"<<((?P<user>\d+)|(?P<role>.{1,100}))>>"#).unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref REGEX_CHANNEL_USER: Regex = Regex::new(r#"\s*<(#|@)(?:!)?(\d+)>\s*"#).unwrap();
 | 
					    pub static ref REGEX_CHANNEL_USER: Regex = Regex::new(r#"\s*<(#|@)(?:!)?(\d+)>\s*"#).unwrap();
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref REGEX_NATURAL_COMMAND_1: Regex = RegexBuilder::new(
 | 
					 | 
				
			||||||
    r#"(?P<time>.*?)(?:\s+)(?:send|say)(?:\s+)(?P<msg>.*?)(?:(?:\s+)to(?:\s+)(?P<mentions>((?:<@\d+>)|(?:<@!\d+>)|(?:<#\d+>)|(?:\s+))+))?$"#
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
        .dot_matches_new_line(true)
 | 
					 | 
				
			||||||
        .build()
 | 
					 | 
				
			||||||
        .unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref REGEX_NATURAL_COMMAND_2: Regex = RegexBuilder::new(
 | 
					 | 
				
			||||||
    r#"(?P<msg>.*)(?:\s+)every(?:\s+)(?P<interval>.*?)(?:(?:\s+)(?:until|for)(?:\s+)(?P<expires>.*?))?$"#
 | 
					 | 
				
			||||||
    )
 | 
					 | 
				
			||||||
        .dot_matches_new_line(true)
 | 
					 | 
				
			||||||
        .build()
 | 
					 | 
				
			||||||
        .unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref SUBSCRIPTION_ROLES: HashSet<u64> = HashSet::from_iter(
 | 
					    pub static ref SUBSCRIPTION_ROLES: HashSet<u64> = HashSet::from_iter(
 | 
				
			||||||
        env::var("SUBSCRIPTION_ROLES")
 | 
					        env::var("SUBSCRIPTION_ROLES")
 | 
				
			||||||
            .map(|var| var
 | 
					            .map(|var| var
 | 
				
			||||||
@@ -54,35 +34,23 @@ lazy_static! {
 | 
				
			|||||||
                .collect::<Vec<u64>>())
 | 
					                .collect::<Vec<u64>>())
 | 
				
			||||||
            .unwrap_or_else(|_| Vec::new())
 | 
					            .unwrap_or_else(|_| Vec::new())
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
 | 
					    pub static ref CNC_GUILD: Option<u64> =
 | 
				
			||||||
    pub static ref CNC_GUILD: Option<u64> = env::var("CNC_GUILD")
 | 
					        env::var("CNC_GUILD").map(|var| var.parse::<u64>().ok()).ok().flatten();
 | 
				
			||||||
        .map(|var| var.parse::<u64>().ok())
 | 
					 | 
				
			||||||
        .ok()
 | 
					 | 
				
			||||||
        .flatten();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref MIN_INTERVAL: i64 = env::var("MIN_INTERVAL")
 | 
					    pub static ref MIN_INTERVAL: i64 = env::var("MIN_INTERVAL")
 | 
				
			||||||
        .ok()
 | 
					        .ok()
 | 
				
			||||||
        .map(|inner| inner.parse::<i64>().ok())
 | 
					        .map(|inner| inner.parse::<i64>().ok())
 | 
				
			||||||
        .flatten()
 | 
					        .flatten()
 | 
				
			||||||
        .unwrap_or(600);
 | 
					        .unwrap_or(600);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref MAX_TIME: i64 = env::var("MAX_TIME")
 | 
					    pub static ref MAX_TIME: i64 = env::var("MAX_TIME")
 | 
				
			||||||
        .ok()
 | 
					        .ok()
 | 
				
			||||||
        .map(|inner| inner.parse::<i64>().ok())
 | 
					        .map(|inner| inner.parse::<i64>().ok())
 | 
				
			||||||
        .flatten()
 | 
					        .flatten()
 | 
				
			||||||
        .unwrap_or(60 * 60 * 24 * 365 * 50);
 | 
					        .unwrap_or(60 * 60 * 24 * 365 * 50);
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref LOCAL_TIMEZONE: String =
 | 
					    pub static ref LOCAL_TIMEZONE: String =
 | 
				
			||||||
        env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string());
 | 
					        env::var("LOCAL_TIMEZONE").unwrap_or_else(|_| "UTC".to_string());
 | 
				
			||||||
 | 
					    pub static ref THEME_COLOR: u32 = env::var("THEME_COLOR")
 | 
				
			||||||
    pub static ref DEFAULT_PREFIX: String =
 | 
					        .map_or(THEME_COLOR_FALLBACK, |inner| u32::from_str_radix(&inner, 16)
 | 
				
			||||||
        env::var("DEFAULT_PREFIX").unwrap_or_else(|_| "$".to_string());
 | 
					            .unwrap_or(THEME_COLOR_FALLBACK));
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref THEME_COLOR: u32 = env::var("THEME_COLOR").map_or(
 | 
					 | 
				
			||||||
        THEME_COLOR_FALLBACK,
 | 
					 | 
				
			||||||
        |inner| u32::from_str_radix(&inner, 16).unwrap_or(THEME_COLOR_FALLBACK)
 | 
					 | 
				
			||||||
    );
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub static ref PYTHON_LOCATION: String =
 | 
					    pub static ref PYTHON_LOCATION: String =
 | 
				
			||||||
        env::var("PYTHON_LOCATION").unwrap_or_else(|_| "venv/bin/python3".to_string());
 | 
					        env::var("PYTHON_LOCATION").unwrap_or_else(|_| "venv/bin/python3".to_string());
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										129
									
								
								src/framework.rs
									
									
									
									
									
								
							
							
						
						
									
										129
									
								
								src/framework.rs
									
									
									
									
									
								
							@@ -7,7 +7,7 @@ use std::{
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use log::info;
 | 
					use log::info;
 | 
				
			||||||
use regex::{Match, Regex, RegexBuilder};
 | 
					use regex::{Regex, RegexBuilder};
 | 
				
			||||||
use serde::{Deserialize, Serialize};
 | 
					use serde::{Deserialize, Serialize};
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{
 | 
				
			||||||
    async_trait,
 | 
					    async_trait,
 | 
				
			||||||
@@ -16,11 +16,11 @@ use serenity::{
 | 
				
			|||||||
    client::Context,
 | 
					    client::Context,
 | 
				
			||||||
    framework::Framework,
 | 
					    framework::Framework,
 | 
				
			||||||
    futures::prelude::future::BoxFuture,
 | 
					    futures::prelude::future::BoxFuture,
 | 
				
			||||||
    http::{CacheHttp, Http},
 | 
					    http::Http,
 | 
				
			||||||
    model::{
 | 
					    model::{
 | 
				
			||||||
        channel::Message,
 | 
					        channel::Message,
 | 
				
			||||||
        guild::{Guild, Member},
 | 
					        guild::{Guild, Member},
 | 
				
			||||||
        id::{ChannelId, GuildId, MessageId, RoleId, UserId},
 | 
					        id::{ChannelId, GuildId, RoleId, UserId},
 | 
				
			||||||
        interactions::{
 | 
					        interactions::{
 | 
				
			||||||
            application_command::{
 | 
					            application_command::{
 | 
				
			||||||
                ApplicationCommand, ApplicationCommandInteraction, ApplicationCommandOptionType,
 | 
					                ApplicationCommand, ApplicationCommandInteraction, ApplicationCommandOptionType,
 | 
				
			||||||
@@ -34,7 +34,7 @@ use serenity::{
 | 
				
			|||||||
    Result as SerenityResult,
 | 
					    Result as SerenityResult,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{models::CtxData, LimitExecutors};
 | 
					use crate::LimitExecutors;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub struct CreateGenericResponse {
 | 
					pub struct CreateGenericResponse {
 | 
				
			||||||
    content: String,
 | 
					    content: String,
 | 
				
			||||||
@@ -89,7 +89,6 @@ impl CreateGenericResponse {
 | 
				
			|||||||
enum InvokeModel {
 | 
					enum InvokeModel {
 | 
				
			||||||
    Slash(ApplicationCommandInteraction),
 | 
					    Slash(ApplicationCommandInteraction),
 | 
				
			||||||
    Component(MessageComponentInteraction),
 | 
					    Component(MessageComponentInteraction),
 | 
				
			||||||
    Text(Message),
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[derive(Clone)]
 | 
					#[derive(Clone)]
 | 
				
			||||||
@@ -108,10 +107,6 @@ impl CommandInvoke {
 | 
				
			|||||||
        Self { model: InvokeModel::Slash(interaction), already_responded: false, deferred: false }
 | 
					        Self { model: InvokeModel::Slash(interaction), already_responded: false, deferred: false }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fn msg(msg: Message) -> Self {
 | 
					 | 
				
			||||||
        Self { model: InvokeModel::Text(msg), already_responded: false, deferred: false }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn defer(&mut self, http: impl AsRef<Http>) {
 | 
					    pub async fn defer(&mut self, http: impl AsRef<Http>) {
 | 
				
			||||||
        if !self.deferred {
 | 
					        if !self.deferred {
 | 
				
			||||||
            match &self.model {
 | 
					            match &self.model {
 | 
				
			||||||
@@ -133,7 +128,6 @@ impl CommandInvoke {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                    self.deferred = true;
 | 
					                    self.deferred = true;
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
                InvokeModel::Text(_) => (),
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -142,7 +136,6 @@ impl CommandInvoke {
 | 
				
			|||||||
        match &self.model {
 | 
					        match &self.model {
 | 
				
			||||||
            InvokeModel::Slash(i) => i.channel_id,
 | 
					            InvokeModel::Slash(i) => i.channel_id,
 | 
				
			||||||
            InvokeModel::Component(i) => i.channel_id,
 | 
					            InvokeModel::Component(i) => i.channel_id,
 | 
				
			||||||
            InvokeModel::Text(m) => m.channel_id,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -150,7 +143,6 @@ impl CommandInvoke {
 | 
				
			|||||||
        match &self.model {
 | 
					        match &self.model {
 | 
				
			||||||
            InvokeModel::Slash(i) => i.guild_id,
 | 
					            InvokeModel::Slash(i) => i.guild_id,
 | 
				
			||||||
            InvokeModel::Component(i) => i.guild_id,
 | 
					            InvokeModel::Component(i) => i.guild_id,
 | 
				
			||||||
            InvokeModel::Text(m) => m.guild_id,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -162,15 +154,13 @@ impl CommandInvoke {
 | 
				
			|||||||
        match &self.model {
 | 
					        match &self.model {
 | 
				
			||||||
            InvokeModel::Slash(i) => i.user.id,
 | 
					            InvokeModel::Slash(i) => i.user.id,
 | 
				
			||||||
            InvokeModel::Component(i) => i.user.id,
 | 
					            InvokeModel::Component(i) => i.user.id,
 | 
				
			||||||
            InvokeModel::Text(m) => m.author.id,
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub async fn member(&self, cache_http: impl CacheHttp) -> Option<Member> {
 | 
					    pub fn member(&self) -> Option<Member> {
 | 
				
			||||||
        match &self.model {
 | 
					        match &self.model {
 | 
				
			||||||
            InvokeModel::Slash(i) => i.member.clone(),
 | 
					            InvokeModel::Slash(i) => i.member.clone(),
 | 
				
			||||||
            InvokeModel::Component(i) => i.member.clone(),
 | 
					            InvokeModel::Component(i) => i.member.clone(),
 | 
				
			||||||
            InvokeModel::Text(m) => m.member(cache_http).await.ok(),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -264,26 +254,6 @@ impl CommandInvoke {
 | 
				
			|||||||
                })
 | 
					                })
 | 
				
			||||||
                .await
 | 
					                .await
 | 
				
			||||||
                .map(|_| ()),
 | 
					                .map(|_| ()),
 | 
				
			||||||
            InvokeModel::Text(m) => m
 | 
					 | 
				
			||||||
                .channel_id
 | 
					 | 
				
			||||||
                .send_message(http, |m| {
 | 
					 | 
				
			||||||
                    m.content(generic_response.content);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if let Some(embed) = generic_response.embed {
 | 
					 | 
				
			||||||
                        m.set_embed(embed);
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if let Some(components) = generic_response.components {
 | 
					 | 
				
			||||||
                        m.components(|c| {
 | 
					 | 
				
			||||||
                            *c = components;
 | 
					 | 
				
			||||||
                            c
 | 
					 | 
				
			||||||
                        });
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    m
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
                .await
 | 
					 | 
				
			||||||
                .map(|_| ()),
 | 
					 | 
				
			||||||
        }?;
 | 
					        }?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        self.already_responded = true;
 | 
					        self.already_responded = true;
 | 
				
			||||||
@@ -484,9 +454,6 @@ pub enum HookResult {
 | 
				
			|||||||
type SlashCommandFn =
 | 
					type SlashCommandFn =
 | 
				
			||||||
    for<'fut> fn(&'fut Context, &'fut mut CommandInvoke, CommandOptions) -> BoxFuture<'fut, ()>;
 | 
					    for<'fut> fn(&'fut Context, &'fut mut CommandInvoke, CommandOptions) -> BoxFuture<'fut, ()>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type TextCommandFn =
 | 
					 | 
				
			||||||
    for<'fut> fn(&'fut Context, &'fut mut CommandInvoke, String) -> BoxFuture<'fut, ()>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type MultiCommandFn = for<'fut> fn(&'fut Context, &'fut mut CommandInvoke) -> BoxFuture<'fut, ()>;
 | 
					type MultiCommandFn = for<'fut> fn(&'fut Context, &'fut mut CommandInvoke) -> BoxFuture<'fut, ()>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub type HookFn = for<'fut> fn(
 | 
					pub type HookFn = for<'fut> fn(
 | 
				
			||||||
@@ -497,16 +464,9 @@ pub type HookFn = for<'fut> fn(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
pub enum CommandFnType {
 | 
					pub enum CommandFnType {
 | 
				
			||||||
    Slash(SlashCommandFn),
 | 
					    Slash(SlashCommandFn),
 | 
				
			||||||
    Text(TextCommandFn),
 | 
					 | 
				
			||||||
    Multi(MultiCommandFn),
 | 
					    Multi(MultiCommandFn),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl CommandFnType {
 | 
					 | 
				
			||||||
    pub fn is_slash(&self) -> bool {
 | 
					 | 
				
			||||||
        !matches!(self, CommandFnType::Text(_))
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct Hook {
 | 
					pub struct Hook {
 | 
				
			||||||
    pub fun: HookFn,
 | 
					    pub fun: HookFn,
 | 
				
			||||||
    pub uuid: u128,
 | 
					    pub uuid: u128,
 | 
				
			||||||
@@ -697,7 +657,6 @@ impl RegexFramework {
 | 
				
			|||||||
        commands: &'a mut CreateApplicationCommands,
 | 
					        commands: &'a mut CreateApplicationCommands,
 | 
				
			||||||
    ) -> &'a mut CreateApplicationCommands {
 | 
					    ) -> &'a mut CreateApplicationCommands {
 | 
				
			||||||
        for command in &self.commands {
 | 
					        for command in &self.commands {
 | 
				
			||||||
            if command.fun.is_slash() {
 | 
					 | 
				
			||||||
            commands.create_application_command(|c| {
 | 
					            commands.create_application_command(|c| {
 | 
				
			||||||
                c.name(command.names[0]).description(command.desc);
 | 
					                c.name(command.names[0]).description(command.desc);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -735,7 +694,6 @@ impl RegexFramework {
 | 
				
			|||||||
                c
 | 
					                c
 | 
				
			||||||
            });
 | 
					            });
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        commands
 | 
					        commands
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -798,7 +756,6 @@ impl RegexFramework {
 | 
				
			|||||||
            match command.fun {
 | 
					            match command.fun {
 | 
				
			||||||
                CommandFnType::Slash(t) => t(&ctx, &mut command_invoke, args).await,
 | 
					                CommandFnType::Slash(t) => t(&ctx, &mut command_invoke, args).await,
 | 
				
			||||||
                CommandFnType::Multi(m) => m(&ctx, &mut command_invoke).await,
 | 
					                CommandFnType::Multi(m) => m(&ctx, &mut command_invoke).await,
 | 
				
			||||||
                _ => (),
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ctx.drop_executing(user_id).await;
 | 
					            ctx.drop_executing(user_id).await;
 | 
				
			||||||
@@ -820,85 +777,11 @@ impl RegexFramework {
 | 
				
			|||||||
        match command.fun {
 | 
					        match command.fun {
 | 
				
			||||||
            CommandFnType::Slash(t) => t(&ctx, command_invoke, command_options).await,
 | 
					            CommandFnType::Slash(t) => t(&ctx, command_invoke, command_options).await,
 | 
				
			||||||
            CommandFnType::Multi(m) => m(&ctx, command_invoke).await,
 | 
					            CommandFnType::Multi(m) => m(&ctx, command_invoke).await,
 | 
				
			||||||
            _ => (),
 | 
					 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[async_trait]
 | 
					#[async_trait]
 | 
				
			||||||
impl Framework for RegexFramework {
 | 
					impl Framework for RegexFramework {
 | 
				
			||||||
    async fn dispatch(&self, ctx: Context, msg: Message) {
 | 
					    async fn dispatch(&self, _ctx: Context, _msg: Message) {}
 | 
				
			||||||
        async fn check_prefix(ctx: &Context, guild: &Guild, prefix_opt: Option<Match<'_>>) -> bool {
 | 
					 | 
				
			||||||
            if let Some(prefix) = prefix_opt {
 | 
					 | 
				
			||||||
                let guild_prefix = ctx.prefix(Some(guild.id)).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                guild_prefix.as_str() == prefix.as_str()
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                true
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // gate to prevent analysing messages unnecessarily
 | 
					 | 
				
			||||||
        if (msg.author.bot && self.ignore_bots) || msg.content.is_empty() {
 | 
					 | 
				
			||||||
            return;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let user_id = msg.author.id;
 | 
					 | 
				
			||||||
        let mut invoke = CommandInvoke::msg(msg.clone());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        // Guild Command
 | 
					 | 
				
			||||||
        if let Some(guild) = msg.guild(&ctx) {
 | 
					 | 
				
			||||||
            if let Some(full_match) = self.command_matcher.captures(&msg.content) {
 | 
					 | 
				
			||||||
                if check_prefix(&ctx, &guild, full_match.name("prefix")).await {
 | 
					 | 
				
			||||||
                    let command = self
 | 
					 | 
				
			||||||
                        .commands_map
 | 
					 | 
				
			||||||
                        .get(&full_match.name("cmd").unwrap().as_str().to_lowercase())
 | 
					 | 
				
			||||||
                        .unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    let channel_data = ctx.channel_data(invoke.channel_id()).await.unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    if !command.can_blacklist || !channel_data.blacklisted {
 | 
					 | 
				
			||||||
                        let args =
 | 
					 | 
				
			||||||
                            full_match.name("args").map(|m| m.as_str()).unwrap_or("").to_string();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if msg.id == MessageId(0) || !ctx.check_executing(user_id).await {
 | 
					 | 
				
			||||||
                            ctx.set_executing(user_id).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            match command.fun {
 | 
					 | 
				
			||||||
                                CommandFnType::Text(t) => t(&ctx, &mut invoke, args).await,
 | 
					 | 
				
			||||||
                                CommandFnType::Multi(m) => m(&ctx, &mut invoke).await,
 | 
					 | 
				
			||||||
                                _ => {}
 | 
					 | 
				
			||||||
                            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            ctx.drop_executing(user_id).await;
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        // DM Command
 | 
					 | 
				
			||||||
        else if self.dm_enabled {
 | 
					 | 
				
			||||||
            if let Some(full_match) = self.dm_regex_matcher.captures(&msg.content[..]) {
 | 
					 | 
				
			||||||
                let command = self
 | 
					 | 
				
			||||||
                    .commands_map
 | 
					 | 
				
			||||||
                    .get(&full_match.name("cmd").unwrap().as_str().to_lowercase())
 | 
					 | 
				
			||||||
                    .unwrap();
 | 
					 | 
				
			||||||
                let args = full_match.name("args").map(|m| m.as_str()).unwrap_or("").to_string();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                let user_id = invoke.author_id();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                if msg.id == MessageId(0) || !ctx.check_executing(user_id).await {
 | 
					 | 
				
			||||||
                    ctx.set_executing(user_id).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    match command.fun {
 | 
					 | 
				
			||||||
                        CommandFnType::Text(t) => t(&ctx, &mut invoke, args).await,
 | 
					 | 
				
			||||||
                        CommandFnType::Multi(m) => m(&ctx, &mut invoke).await,
 | 
					 | 
				
			||||||
                        _ => {}
 | 
					 | 
				
			||||||
                    };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    ctx.drop_executing(user_id).await;
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -107,7 +107,7 @@ pub async fn check_managed_permissions(
 | 
				
			|||||||
            return HookResult::Continue;
 | 
					            return HookResult::Continue;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let member = invoke.member(&ctx).await.unwrap();
 | 
					        let member = invoke.member().unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let pool = ctx
 | 
					        let pool = ctx
 | 
				
			||||||
            .data
 | 
					            .data
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										75
									
								
								src/main.rs
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								src/main.rs
									
									
									
									
									
								
							@@ -13,19 +13,17 @@ mod time_parser;
 | 
				
			|||||||
use std::{collections::HashMap, env, sync::Arc, time::Instant};
 | 
					use std::{collections::HashMap, env, sync::Arc, time::Instant};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use chrono_tz::Tz;
 | 
					use chrono_tz::Tz;
 | 
				
			||||||
use dashmap::DashMap;
 | 
					 | 
				
			||||||
use dotenv::dotenv;
 | 
					use dotenv::dotenv;
 | 
				
			||||||
use log::info;
 | 
					use log::info;
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{
 | 
				
			||||||
    async_trait,
 | 
					    async_trait,
 | 
				
			||||||
    cache::Cache,
 | 
					 | 
				
			||||||
    client::{bridge::gateway::GatewayIntents, Client},
 | 
					    client::{bridge::gateway::GatewayIntents, Client},
 | 
				
			||||||
    futures::TryFutureExt,
 | 
					    futures::TryFutureExt,
 | 
				
			||||||
    http::{client::Http, CacheHttp},
 | 
					    http::{client::Http, CacheHttp},
 | 
				
			||||||
    model::{
 | 
					    model::{
 | 
				
			||||||
        channel::{GuildChannel, Message},
 | 
					        channel::GuildChannel,
 | 
				
			||||||
        gateway::{Activity, Ready},
 | 
					        gateway::{Activity, Ready},
 | 
				
			||||||
        guild::{Guild, GuildUnavailable},
 | 
					        guild::Guild,
 | 
				
			||||||
        id::{GuildId, UserId},
 | 
					        id::{GuildId, UserId},
 | 
				
			||||||
        interactions::Interaction,
 | 
					        interactions::Interaction,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@@ -38,17 +36,11 @@ use tokio::sync::RwLock;
 | 
				
			|||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    commands::{info_cmds, moderation_cmds, reminder_cmds, todo_cmds},
 | 
					    commands::{info_cmds, moderation_cmds, reminder_cmds, todo_cmds},
 | 
				
			||||||
    component_models::ComponentDataModel,
 | 
					    component_models::ComponentDataModel,
 | 
				
			||||||
    consts::{CNC_GUILD, DEFAULT_PREFIX, SUBSCRIPTION_ROLES, THEME_COLOR},
 | 
					    consts::{CNC_GUILD, SUBSCRIPTION_ROLES, THEME_COLOR},
 | 
				
			||||||
    framework::RegexFramework,
 | 
					    framework::RegexFramework,
 | 
				
			||||||
    models::{command_macro::CommandMacro, guild_data::GuildData},
 | 
					    models::command_macro::CommandMacro,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct GuildDataCache;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl TypeMapKey for GuildDataCache {
 | 
					 | 
				
			||||||
    type Value = Arc<DashMap<GuildId, Arc<RwLock<GuildData>>>>;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
struct SQLPool;
 | 
					struct SQLPool;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl TypeMapKey for SQLPool {
 | 
					impl TypeMapKey for SQLPool {
 | 
				
			||||||
@@ -156,20 +148,6 @@ DELETE FROM channels WHERE channel = ?
 | 
				
			|||||||
        if is_new {
 | 
					        if is_new {
 | 
				
			||||||
            let guild_id = guild.id.as_u64().to_owned();
 | 
					            let guild_id = guild.id.as_u64().to_owned();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                let pool = ctx
 | 
					 | 
				
			||||||
                    .data
 | 
					 | 
				
			||||||
                    .read()
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
                    .get::<SQLPool>()
 | 
					 | 
				
			||||||
                    .cloned()
 | 
					 | 
				
			||||||
                    .expect("Could not get SQLPool from data");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                GuildData::from_guild(guild, &pool).await.unwrap_or_else(|_| {
 | 
					 | 
				
			||||||
                    panic!("Failed to create new guild object for {}", guild_id)
 | 
					 | 
				
			||||||
                });
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if let Ok(token) = env::var("DISCORDBOTS_TOKEN") {
 | 
					            if let Ok(token) = env::var("DISCORDBOTS_TOKEN") {
 | 
				
			||||||
                let shard_count = ctx.cache.shard_count();
 | 
					                let shard_count = ctx.cache.shard_count();
 | 
				
			||||||
                let current_shard_id = shard_id(guild_id, shard_count);
 | 
					                let current_shard_id = shard_id(guild_id, shard_count);
 | 
				
			||||||
@@ -214,34 +192,6 @@ DELETE FROM channels WHERE channel = ?
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async fn guild_delete(
 | 
					 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        ctx: Context,
 | 
					 | 
				
			||||||
        deleted_guild: GuildUnavailable,
 | 
					 | 
				
			||||||
        _guild: Option<Guild>,
 | 
					 | 
				
			||||||
    ) {
 | 
					 | 
				
			||||||
        let pool = ctx
 | 
					 | 
				
			||||||
            .data
 | 
					 | 
				
			||||||
            .read()
 | 
					 | 
				
			||||||
            .await
 | 
					 | 
				
			||||||
            .get::<SQLPool>()
 | 
					 | 
				
			||||||
            .cloned()
 | 
					 | 
				
			||||||
            .expect("Could not get SQLPool from data");
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let guild_data_cache = ctx.data.read().await.get::<GuildDataCache>().cloned().unwrap();
 | 
					 | 
				
			||||||
        guild_data_cache.remove(&deleted_guild.id);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        sqlx::query!(
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
DELETE FROM guilds WHERE guild = ?
 | 
					 | 
				
			||||||
            ",
 | 
					 | 
				
			||||||
            deleted_guild.id.as_u64()
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .execute(&pool)
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
        .unwrap();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async fn ready(&self, ctx: Context, _: Ready) {
 | 
					    async fn ready(&self, ctx: Context, _: Ready) {
 | 
				
			||||||
        ctx.set_activity(Activity::watching("for /remind")).await;
 | 
					        ctx.set_activity(Activity::watching("for /remind")).await;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -288,7 +238,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
 | 
				
			|||||||
    let dm_enabled = env::var("DM_ENABLED").map_or(true, |var| var == "1");
 | 
					    let dm_enabled = env::var("DM_ENABLED").map_or(true, |var| var == "1");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    let framework = RegexFramework::new(logged_in_id)
 | 
					    let framework = RegexFramework::new(logged_in_id)
 | 
				
			||||||
        .default_prefix(DEFAULT_PREFIX.clone())
 | 
					        .default_prefix("")
 | 
				
			||||||
        .case_insensitive(env::var("CASE_INSENSITIVE").map_or(true, |var| var == "1"))
 | 
					        .case_insensitive(env::var("CASE_INSENSITIVE").map_or(true, |var| var == "1"))
 | 
				
			||||||
        .ignore_bots(env::var("IGNORE_BOTS").map_or(true, |var| var == "1"))
 | 
					        .ignore_bots(env::var("IGNORE_BOTS").map_or(true, |var| var == "1"))
 | 
				
			||||||
        .debug_guild(env::var("DEBUG_GUILD").map_or(None, |g| {
 | 
					        .debug_guild(env::var("DEBUG_GUILD").map_or(None, |g| {
 | 
				
			||||||
@@ -337,8 +287,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
 | 
				
			|||||||
        .expect("Error occurred creating client");
 | 
					        .expect("Error occurred creating client");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        let guild_data_cache = dashmap::DashMap::new();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let pool = MySqlPool::connect(
 | 
					        let pool = MySqlPool::connect(
 | 
				
			||||||
            &env::var("DATABASE_URL").expect("Missing DATABASE_URL from environment"),
 | 
					            &env::var("DATABASE_URL").expect("Missing DATABASE_URL from environment"),
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
@@ -357,7 +305,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        let mut data = client.data.write().await;
 | 
					        let mut data = client.data.write().await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data.insert::<GuildDataCache>(Arc::new(guild_data_cache));
 | 
					 | 
				
			||||||
        data.insert::<CurrentlyExecuting>(Arc::new(RwLock::new(HashMap::new())));
 | 
					        data.insert::<CurrentlyExecuting>(Arc::new(RwLock::new(HashMap::new())));
 | 
				
			||||||
        data.insert::<SQLPool>(pool);
 | 
					        data.insert::<SQLPool>(pool);
 | 
				
			||||||
        data.insert::<PopularTimezones>(Arc::new(popular_timezones));
 | 
					        data.insert::<PopularTimezones>(Arc::new(popular_timezones));
 | 
				
			||||||
@@ -415,15 +362,3 @@ pub async fn check_subscription(cache_http: impl CacheHttp, user_id: impl Into<U
 | 
				
			|||||||
        true
 | 
					        true
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
pub async fn check_subscription_on_message(
 | 
					 | 
				
			||||||
    cache_http: impl CacheHttp + AsRef<Cache>,
 | 
					 | 
				
			||||||
    msg: &Message,
 | 
					 | 
				
			||||||
) -> bool {
 | 
					 | 
				
			||||||
    check_subscription(&cache_http, &msg.author).await
 | 
					 | 
				
			||||||
        || if let Some(guild) = msg.guild(&cache_http) {
 | 
					 | 
				
			||||||
            check_subscription(&cache_http, guild.owner_id).await
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            false
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,77 +0,0 @@
 | 
				
			|||||||
use log::error;
 | 
					 | 
				
			||||||
use serenity::model::guild::Guild;
 | 
					 | 
				
			||||||
use sqlx::MySqlPool;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::consts::DEFAULT_PREFIX;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct GuildData {
 | 
					 | 
				
			||||||
    pub id: u32,
 | 
					 | 
				
			||||||
    pub name: Option<String>,
 | 
					 | 
				
			||||||
    pub prefix: String,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl GuildData {
 | 
					 | 
				
			||||||
    pub async fn from_guild(guild: Guild, pool: &MySqlPool) -> Result<Self, sqlx::Error> {
 | 
					 | 
				
			||||||
        let guild_id = guild.id.as_u64().to_owned();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        match sqlx::query_as!(
 | 
					 | 
				
			||||||
            Self,
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
SELECT id, name, prefix FROM guilds WHERE guild = ?
 | 
					 | 
				
			||||||
            ",
 | 
					 | 
				
			||||||
            guild_id
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .fetch_one(pool)
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            Ok(mut g) => {
 | 
					 | 
				
			||||||
                g.name = Some(guild.name);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                Ok(g)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Err(sqlx::Error::RowNotFound) => {
 | 
					 | 
				
			||||||
                sqlx::query!(
 | 
					 | 
				
			||||||
                    "
 | 
					 | 
				
			||||||
INSERT INTO guilds (guild, name, prefix) VALUES (?, ?, ?)
 | 
					 | 
				
			||||||
                    ",
 | 
					 | 
				
			||||||
                    guild_id,
 | 
					 | 
				
			||||||
                    guild.name,
 | 
					 | 
				
			||||||
                    *DEFAULT_PREFIX
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                .execute(&pool.clone())
 | 
					 | 
				
			||||||
                .await?;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                Ok(sqlx::query_as!(
 | 
					 | 
				
			||||||
                    Self,
 | 
					 | 
				
			||||||
                    "
 | 
					 | 
				
			||||||
SELECT id, name, prefix FROM guilds WHERE guild = ?
 | 
					 | 
				
			||||||
                    ",
 | 
					 | 
				
			||||||
                    guild_id
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                .fetch_one(pool)
 | 
					 | 
				
			||||||
                .await?)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            Err(e) => {
 | 
					 | 
				
			||||||
                error!("Unexpected error in guild query: {:?}", e);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                Err(e)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn commit_changes(&self, pool: &MySqlPool) {
 | 
					 | 
				
			||||||
        sqlx::query!(
 | 
					 | 
				
			||||||
            "
 | 
					 | 
				
			||||||
UPDATE guilds SET name = ?, prefix = ? WHERE id = ?
 | 
					 | 
				
			||||||
            ",
 | 
					 | 
				
			||||||
            self.name,
 | 
					 | 
				
			||||||
            self.prefix,
 | 
					 | 
				
			||||||
            self.id
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
        .execute(pool)
 | 
					 | 
				
			||||||
        .await
 | 
					 | 
				
			||||||
        .unwrap();
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
@@ -1,35 +1,23 @@
 | 
				
			|||||||
pub mod channel_data;
 | 
					pub mod channel_data;
 | 
				
			||||||
pub mod command_macro;
 | 
					pub mod command_macro;
 | 
				
			||||||
pub mod guild_data;
 | 
					 | 
				
			||||||
pub mod reminder;
 | 
					pub mod reminder;
 | 
				
			||||||
pub mod timer;
 | 
					pub mod timer;
 | 
				
			||||||
pub mod user_data;
 | 
					pub mod user_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
use std::sync::Arc;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use chrono_tz::Tz;
 | 
					use chrono_tz::Tz;
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{
 | 
				
			||||||
    async_trait,
 | 
					    async_trait,
 | 
				
			||||||
    model::id::{ChannelId, GuildId, UserId},
 | 
					    model::id::{ChannelId, UserId},
 | 
				
			||||||
    prelude::Context,
 | 
					    prelude::Context,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use tokio::sync::RwLock;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    consts::DEFAULT_PREFIX,
 | 
					    models::{channel_data::ChannelData, user_data::UserData},
 | 
				
			||||||
    models::{channel_data::ChannelData, guild_data::GuildData, user_data::UserData},
 | 
					    SQLPool,
 | 
				
			||||||
    GuildDataCache, SQLPool,
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[async_trait]
 | 
					#[async_trait]
 | 
				
			||||||
pub trait CtxData {
 | 
					pub trait CtxData {
 | 
				
			||||||
    async fn guild_data<G: Into<GuildId> + Send + Sync>(
 | 
					 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        guild_id: G,
 | 
					 | 
				
			||||||
    ) -> Result<Arc<RwLock<GuildData>>, sqlx::Error>;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async fn prefix<G: Into<GuildId> + Send + Sync>(&self, guild_id: Option<G>) -> String;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async fn user_data<U: Into<UserId> + Send + Sync>(
 | 
					    async fn user_data<U: Into<UserId> + Send + Sync>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        user_id: U,
 | 
					        user_id: U,
 | 
				
			||||||
@@ -45,45 +33,6 @@ pub trait CtxData {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#[async_trait]
 | 
					#[async_trait]
 | 
				
			||||||
impl CtxData for Context {
 | 
					impl CtxData for Context {
 | 
				
			||||||
    async fn guild_data<G: Into<GuildId> + Send + Sync>(
 | 
					 | 
				
			||||||
        &self,
 | 
					 | 
				
			||||||
        guild_id: G,
 | 
					 | 
				
			||||||
    ) -> Result<Arc<RwLock<GuildData>>, sqlx::Error> {
 | 
					 | 
				
			||||||
        let guild_id = guild_id.into();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let guild = guild_id.to_guild_cached(&self.cache).unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let guild_cache = self.data.read().await.get::<GuildDataCache>().cloned().unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let x = if let Some(guild_data) = guild_cache.get(&guild_id) {
 | 
					 | 
				
			||||||
            Ok(guild_data.clone())
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            let pool = self.data.read().await.get::<SQLPool>().cloned().unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            match GuildData::from_guild(guild, &pool).await {
 | 
					 | 
				
			||||||
                Ok(d) => {
 | 
					 | 
				
			||||||
                    let lock = Arc::new(RwLock::new(d));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    guild_cache.insert(guild_id, lock.clone());
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    Ok(lock)
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                Err(e) => Err(e),
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        x
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async fn prefix<G: Into<GuildId> + Send + Sync>(&self, guild_id: Option<G>) -> String {
 | 
					 | 
				
			||||||
        if let Some(guild_id) = guild_id {
 | 
					 | 
				
			||||||
            self.guild_data(guild_id).await.unwrap().read().await.prefix.clone()
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            DEFAULT_PREFIX.clone()
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    async fn user_data<U: Into<UserId> + Send + Sync>(
 | 
					    async fn user_data<U: Into<UserId> + Send + Sync>(
 | 
				
			||||||
        &self,
 | 
					        &self,
 | 
				
			||||||
        user_id: U,
 | 
					        user_id: U,
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user