removed dead code
This commit is contained in:
		@@ -41,10 +41,8 @@ __Other Variables__
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
### Todo List
 | 
					### Todo List
 | 
				
			||||||
 | 
					
 | 
				
			||||||
* Implement remainder of the `macro` command
 | 
					 | 
				
			||||||
* Convert aliases to macros
 | 
					* Convert aliases to macros
 | 
				
			||||||
* Block users from interacting with another users' components
 | 
					* Block users from interacting with another users' components
 | 
				
			||||||
* Split out framework
 | 
					 | 
				
			||||||
* Help command
 | 
					* Help command
 | 
				
			||||||
* Change all db keys to be discord IDs
 | 
					* Change all db keys to be discord IDs
 | 
				
			||||||
* Test everything
 | 
					* Test everything
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,13 +2,13 @@ use chrono::offset::Utc;
 | 
				
			|||||||
use chrono_tz::{Tz, TZ_VARIANTS};
 | 
					use chrono_tz::{Tz, TZ_VARIANTS};
 | 
				
			||||||
use levenshtein::levenshtein;
 | 
					use levenshtein::levenshtein;
 | 
				
			||||||
use regex_command_attr::command;
 | 
					use regex_command_attr::command;
 | 
				
			||||||
use serenity::{
 | 
					use serenity::{client::Context, model::misc::Mentionable};
 | 
				
			||||||
    client::Context,
 | 
					 | 
				
			||||||
    model::{id::GuildId, misc::Mentionable},
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    component_models::{pager::Pager, ComponentDataModel, Restrict},
 | 
					    component_models::{
 | 
				
			||||||
 | 
					        pager::{MacroPager, Pager},
 | 
				
			||||||
 | 
					        ComponentDataModel, Restrict,
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    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},
 | 
				
			||||||
@@ -16,52 +16,6 @@ use crate::{
 | 
				
			|||||||
    PopularTimezones, RecordingMacros, RegexFramework, SQLPool,
 | 
					    PopularTimezones, RecordingMacros, RegexFramework, SQLPool,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command("blacklist")]
 | 
					 | 
				
			||||||
#[description("Block channels from using bot commands")]
 | 
					 | 
				
			||||||
#[arg(
 | 
					 | 
				
			||||||
    name = "channel",
 | 
					 | 
				
			||||||
    description = "The channel to blacklist",
 | 
					 | 
				
			||||||
    kind = "Channel",
 | 
					 | 
				
			||||||
    required = false
 | 
					 | 
				
			||||||
)]
 | 
					 | 
				
			||||||
#[supports_dm(false)]
 | 
					 | 
				
			||||||
#[hook(CHECK_GUILD_PERMISSIONS_HOOK)]
 | 
					 | 
				
			||||||
#[can_blacklist(false)]
 | 
					 | 
				
			||||||
async fn blacklist(ctx: &Context, invoke: &mut CommandInvoke, args: CommandOptions) {
 | 
					 | 
				
			||||||
    let pool = ctx.data.read().await.get::<SQLPool>().cloned().unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let channel = match args.get("channel") {
 | 
					 | 
				
			||||||
        Some(OptionValue::Channel(channel_id)) => *channel_id,
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        _ => invoke.channel_id(),
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    .to_channel_cached(&ctx)
 | 
					 | 
				
			||||||
    .unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let mut channel_data = ChannelData::from_channel(&channel, &pool).await.unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    channel_data.blacklisted = !channel_data.blacklisted;
 | 
					 | 
				
			||||||
    channel_data.commit_changes(&pool).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if channel_data.blacklisted {
 | 
					 | 
				
			||||||
        let _ = invoke
 | 
					 | 
				
			||||||
            .respond(
 | 
					 | 
				
			||||||
                ctx.http.clone(),
 | 
					 | 
				
			||||||
                CreateGenericResponse::new()
 | 
					 | 
				
			||||||
                    .content(format!("{} has been blacklisted", channel.mention())),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        let _ = invoke
 | 
					 | 
				
			||||||
            .respond(
 | 
					 | 
				
			||||||
                ctx.http.clone(),
 | 
					 | 
				
			||||||
                CreateGenericResponse::new()
 | 
					 | 
				
			||||||
                    .content(format!("{} has been removed from the blacklist", channel.mention())),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[command("timezone")]
 | 
					#[command("timezone")]
 | 
				
			||||||
#[description("Select your timezone")]
 | 
					#[description("Select your timezone")]
 | 
				
			||||||
#[arg(
 | 
					#[arg(
 | 
				
			||||||
@@ -173,44 +127,6 @@ You may want to use one of the popular timezones below, otherwise click [here](h
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[command("prefix")]
 | 
					 | 
				
			||||||
#[description("Configure a prefix for text-based commands (deprecated)")]
 | 
					 | 
				
			||||||
#[supports_dm(false)]
 | 
					 | 
				
			||||||
#[hook(CHECK_GUILD_PERMISSIONS_HOOK)]
 | 
					 | 
				
			||||||
async fn prefix(ctx: &Context, invoke: &mut CommandInvoke, args: String) {
 | 
					 | 
				
			||||||
    let pool = ctx.data.read().await.get::<SQLPool>().cloned().unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let guild_data = ctx.guild_data(invoke.guild_id().unwrap()).await.unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if args.len() > 5 {
 | 
					 | 
				
			||||||
        let _ = invoke
 | 
					 | 
				
			||||||
            .respond(
 | 
					 | 
				
			||||||
                ctx.http.clone(),
 | 
					 | 
				
			||||||
                CreateGenericResponse::new().content("Please select a prefix under 5 characters"),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await;
 | 
					 | 
				
			||||||
    } else if args.is_empty() {
 | 
					 | 
				
			||||||
        let _ = invoke
 | 
					 | 
				
			||||||
            .respond(
 | 
					 | 
				
			||||||
                ctx.http.clone(),
 | 
					 | 
				
			||||||
                CreateGenericResponse::new()
 | 
					 | 
				
			||||||
                    .content("Please use this command as `@reminder-bot prefix <prefix>`"),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await;
 | 
					 | 
				
			||||||
    } else {
 | 
					 | 
				
			||||||
        guild_data.write().await.prefix = args;
 | 
					 | 
				
			||||||
        guild_data.read().await.commit_changes(&pool).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        let _ = invoke
 | 
					 | 
				
			||||||
            .respond(
 | 
					 | 
				
			||||||
                ctx.http.clone(),
 | 
					 | 
				
			||||||
                CreateGenericResponse::new()
 | 
					 | 
				
			||||||
                    .content(format!("Prefix changed to {}", guild_data.read().await.prefix)),
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#[command("restrict")]
 | 
					#[command("restrict")]
 | 
				
			||||||
#[description("Configure which roles can use commands on the bot")]
 | 
					#[description("Configure which roles can use commands on the bot")]
 | 
				
			||||||
#[arg(
 | 
					#[arg(
 | 
				
			||||||
@@ -402,9 +318,9 @@ Any commands ran as part of recording will be inconsequential")
 | 
				
			|||||||
        "list" => {
 | 
					        "list" => {
 | 
				
			||||||
            let macros = CommandMacro::from_guild(ctx, invoke.guild_id().unwrap()).await;
 | 
					            let macros = CommandMacro::from_guild(ctx, invoke.guild_id().unwrap()).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            let resp = show_macro_page(¯os, 0, invoke.guild_id().unwrap());
 | 
					            let resp = show_macro_page(¯os, 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            invoke.respond(&ctx, resp).await;
 | 
					            invoke.respond(&ctx, resp).await.unwrap();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        "run" => {
 | 
					        "run" => {
 | 
				
			||||||
            let macro_name = args.get("name").unwrap().to_string();
 | 
					            let macro_name = args.get("name").unwrap().to_string();
 | 
				
			||||||
@@ -456,7 +372,10 @@ Any commands ran as part of recording will be inconsequential")
 | 
				
			|||||||
            .await
 | 
					            .await
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                Ok(row) => {
 | 
					                Ok(row) => {
 | 
				
			||||||
                    sqlx::query!("DELETE FROM macro WHERE id = ?", row.id).execute(&pool).await;
 | 
					                    sqlx::query!("DELETE FROM macro WHERE id = ?", row.id)
 | 
				
			||||||
 | 
					                        .execute(&pool)
 | 
				
			||||||
 | 
					                        .await
 | 
				
			||||||
 | 
					                        .unwrap();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    let _ = invoke
 | 
					                    let _ = invoke
 | 
				
			||||||
                        .respond(
 | 
					                        .respond(
 | 
				
			||||||
@@ -510,12 +429,8 @@ pub fn max_macro_page(macros: &[CommandMacro]) -> usize {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn show_macro_page(
 | 
					pub fn show_macro_page(macros: &[CommandMacro], page: usize) -> CreateGenericResponse {
 | 
				
			||||||
    macros: &[CommandMacro],
 | 
					    let pager = MacroPager::new(page);
 | 
				
			||||||
    page: usize,
 | 
					 | 
				
			||||||
    guild_id: GuildId,
 | 
					 | 
				
			||||||
) -> CreateGenericResponse {
 | 
					 | 
				
			||||||
    let pager = Pager::new(page, guild_id);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if macros.is_empty() {
 | 
					    if macros.is_empty() {
 | 
				
			||||||
        return CreateGenericResponse::new().embed(|e| {
 | 
					        return CreateGenericResponse::new().embed(|e| {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -16,15 +16,10 @@ use crate::{
 | 
				
			|||||||
        pager::{DelPager, LookPager, Pager},
 | 
					        pager::{DelPager, LookPager, Pager},
 | 
				
			||||||
        ComponentDataModel, DelSelector,
 | 
					        ComponentDataModel, DelSelector,
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    consts::{
 | 
					    consts::{EMBED_DESCRIPTION_MAX_LENGTH, REGEX_CHANNEL_USER, SELECT_MAX_ENTRIES, THEME_COLOR},
 | 
				
			||||||
        EMBED_DESCRIPTION_MAX_LENGTH, REGEX_CHANNEL_USER, REGEX_NATURAL_COMMAND_1,
 | 
					 | 
				
			||||||
        REGEX_NATURAL_COMMAND_2, SELECT_MAX_ENTRIES, 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::{
 | 
					    models::{
 | 
				
			||||||
        channel_data::ChannelData,
 | 
					 | 
				
			||||||
        guild_data::GuildData,
 | 
					 | 
				
			||||||
        reminder::{
 | 
					        reminder::{
 | 
				
			||||||
            builder::{MultiReminderBuilder, ReminderScope},
 | 
					            builder::{MultiReminderBuilder, ReminderScope},
 | 
				
			||||||
            content::Content,
 | 
					            content::Content,
 | 
				
			||||||
@@ -704,6 +699,7 @@ async fn remind(ctx: &Context, invoke: &mut CommandInvoke, args: CommandOptions)
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // todo gate this on patreon subscription
 | 
				
			||||||
            let interval = args
 | 
					            let interval = args
 | 
				
			||||||
                .get("repeat")
 | 
					                .get("repeat")
 | 
				
			||||||
                .map(|arg| {
 | 
					                .map(|arg| {
 | 
				
			||||||
@@ -805,178 +801,3 @@ fn parse_mention_list(mentions: &str) -> Vec<ReminderScope> {
 | 
				
			|||||||
        })
 | 
					        })
 | 
				
			||||||
        .collect::<Vec<ReminderScope>>()
 | 
					        .collect::<Vec<ReminderScope>>()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
#[command("natural")]
 | 
					 | 
				
			||||||
#[permission_level(Managed)]
 | 
					 | 
				
			||||||
async fn natural(ctx: &Context, msg: &Message, args: String) {
 | 
					 | 
				
			||||||
    let (pool, lm) = get_ctx_data(&ctx).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    let user_data = UserData::from_user(&msg.author, &ctx, &pool).await.unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    match REGEX_NATURAL_COMMAND_1.captures(&args) {
 | 
					 | 
				
			||||||
        Some(captures) => {
 | 
					 | 
				
			||||||
            let (expires, interval, string_content) =
 | 
					 | 
				
			||||||
                if check_subscription_on_message(&ctx, msg).await {
 | 
					 | 
				
			||||||
                    let rest_content = captures.name("msg").unwrap().as_str();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    match REGEX_NATURAL_COMMAND_2.captures(rest_content) {
 | 
					 | 
				
			||||||
                        Some(secondary_captures) => {
 | 
					 | 
				
			||||||
                            let expires =
 | 
					 | 
				
			||||||
                                if let Some(expires_crop) = secondary_captures.name("expires") {
 | 
					 | 
				
			||||||
                                    natural_parser(expires_crop.as_str(), &user_data.timezone).await
 | 
					 | 
				
			||||||
                                } else {
 | 
					 | 
				
			||||||
                                    None
 | 
					 | 
				
			||||||
                                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            let interval =
 | 
					 | 
				
			||||||
                                if let Some(interval_crop) = secondary_captures.name("interval") {
 | 
					 | 
				
			||||||
                                    humantime::parse_duration(interval_crop.as_str())
 | 
					 | 
				
			||||||
                                        .or_else(|_| {
 | 
					 | 
				
			||||||
                                            humantime::parse_duration(&format!(
 | 
					 | 
				
			||||||
                                                "1 {}",
 | 
					 | 
				
			||||||
                                                interval_crop.as_str()
 | 
					 | 
				
			||||||
                                            ))
 | 
					 | 
				
			||||||
                                        })
 | 
					 | 
				
			||||||
                                        .map(|duration| duration.as_secs() as i64)
 | 
					 | 
				
			||||||
                                        .ok()
 | 
					 | 
				
			||||||
                                } else {
 | 
					 | 
				
			||||||
                                    None
 | 
					 | 
				
			||||||
                                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                            (
 | 
					 | 
				
			||||||
                                expires,
 | 
					 | 
				
			||||||
                                interval,
 | 
					 | 
				
			||||||
                                if interval.is_some() {
 | 
					 | 
				
			||||||
                                    secondary_captures.name("msg").unwrap().as_str()
 | 
					 | 
				
			||||||
                                } else {
 | 
					 | 
				
			||||||
                                    rest_content
 | 
					 | 
				
			||||||
                                },
 | 
					 | 
				
			||||||
                            )
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        None => (None, None, rest_content),
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    (None, None, captures.name("msg").unwrap().as_str())
 | 
					 | 
				
			||||||
                };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            let location_ids = if let Some(mentions) = captures.name("mentions").map(|m| m.as_str())
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                parse_mention_list(mentions)
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                vec![ReminderScope::Channel(msg.channel_id.into())]
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if let Some(timestamp) =
 | 
					 | 
				
			||||||
                natural_parser(captures.name("time").unwrap().as_str(), &user_data.timezone).await
 | 
					 | 
				
			||||||
            {
 | 
					 | 
				
			||||||
                let content_res = Content::build(string_content, msg).await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                match content_res {
 | 
					 | 
				
			||||||
                    Ok(mut content) => {
 | 
					 | 
				
			||||||
                        if let Some(guild) = msg.guild(&ctx) {
 | 
					 | 
				
			||||||
                            content.substitute(guild);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let user_data = ctx.user_data(&msg.author).await.unwrap();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let mut builder = MultiReminderBuilder::new(ctx, msg.guild_id)
 | 
					 | 
				
			||||||
                            .author(user_data)
 | 
					 | 
				
			||||||
                            .content(content)
 | 
					 | 
				
			||||||
                            .interval(interval)
 | 
					 | 
				
			||||||
                            .expires(expires)
 | 
					 | 
				
			||||||
                            .time(timestamp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        builder.set_scopes(location_ids);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let (errors, successes) = builder.build().await;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let success_part = match successes.len() {
 | 
					 | 
				
			||||||
                            0 => "".to_string(),
 | 
					 | 
				
			||||||
                            n => format!(
 | 
					 | 
				
			||||||
                                "Reminder{s} for {locations} set for <t:{offset}:R>",
 | 
					 | 
				
			||||||
                                s = if n > 1 { "s" } else { "" },
 | 
					 | 
				
			||||||
                                locations = successes
 | 
					 | 
				
			||||||
                                    .iter()
 | 
					 | 
				
			||||||
                                    .map(|l| l.mention())
 | 
					 | 
				
			||||||
                                    .collect::<Vec<String>>()
 | 
					 | 
				
			||||||
                                    .join(", "),
 | 
					 | 
				
			||||||
                                offset = timestamp
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let error_part = match errors.len() {
 | 
					 | 
				
			||||||
                            0 => "".to_string(),
 | 
					 | 
				
			||||||
                            n => format!(
 | 
					 | 
				
			||||||
                                "{n} reminder{s} failed to set:\n{errors}",
 | 
					 | 
				
			||||||
                                s = if n > 1 { "s" } else { "" },
 | 
					 | 
				
			||||||
                                n = n,
 | 
					 | 
				
			||||||
                                errors = errors
 | 
					 | 
				
			||||||
                                    .iter()
 | 
					 | 
				
			||||||
                                    .map(|e| e.display(true))
 | 
					 | 
				
			||||||
                                    .collect::<Vec<String>>()
 | 
					 | 
				
			||||||
                                    .join("\n")
 | 
					 | 
				
			||||||
                            ),
 | 
					 | 
				
			||||||
                        };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        let _ = msg
 | 
					 | 
				
			||||||
                            .channel_id
 | 
					 | 
				
			||||||
                            .send_message(&ctx, |m| {
 | 
					 | 
				
			||||||
                                m.embed(|e| {
 | 
					 | 
				
			||||||
                                    e.title(format!(
 | 
					 | 
				
			||||||
                                        "{n} Reminder{s} Set",
 | 
					 | 
				
			||||||
                                        n = successes.len(),
 | 
					 | 
				
			||||||
                                        s = if successes.len() > 1 { "s" } else { "" }
 | 
					 | 
				
			||||||
                                    ))
 | 
					 | 
				
			||||||
                                    .description(format!("{}\n\n{}", success_part, error_part))
 | 
					 | 
				
			||||||
                                    .color(*THEME_COLOR)
 | 
					 | 
				
			||||||
                                })
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                            .await;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                    Err(content_error) => {
 | 
					 | 
				
			||||||
                        let _ = msg
 | 
					 | 
				
			||||||
                            .channel_id
 | 
					 | 
				
			||||||
                            .send_message(ctx, |m| {
 | 
					 | 
				
			||||||
                                m.embed(move |e| {
 | 
					 | 
				
			||||||
                                    e.title("0 Reminders Set")
 | 
					 | 
				
			||||||
                                        .description(content_error.to_string())
 | 
					 | 
				
			||||||
                                        .color(*THEME_COLOR)
 | 
					 | 
				
			||||||
                                })
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                            .await;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                let _ = msg
 | 
					 | 
				
			||||||
                    .channel_id
 | 
					 | 
				
			||||||
                    .send_message(ctx, |m| {
 | 
					 | 
				
			||||||
                        m.embed(move |e| {
 | 
					 | 
				
			||||||
                            e.title(
 | 
					 | 
				
			||||||
                                lm.get(&user_data.language, "remind/title")
 | 
					 | 
				
			||||||
                                    .replace("{number}", "0"),
 | 
					 | 
				
			||||||
                            )
 | 
					 | 
				
			||||||
                            .description(lm.get(&user_data.language, "natural/invalid_time"))
 | 
					 | 
				
			||||||
                            .color(*THEME_COLOR)
 | 
					 | 
				
			||||||
                        })
 | 
					 | 
				
			||||||
                    })
 | 
					 | 
				
			||||||
                    .await;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        None => {
 | 
					 | 
				
			||||||
            command_help(
 | 
					 | 
				
			||||||
                ctx,
 | 
					 | 
				
			||||||
                msg,
 | 
					 | 
				
			||||||
                lm,
 | 
					 | 
				
			||||||
                &ctx.prefix(msg.guild_id).await,
 | 
					 | 
				
			||||||
                &user_data.language,
 | 
					 | 
				
			||||||
                "natural",
 | 
					 | 
				
			||||||
            )
 | 
					 | 
				
			||||||
            .await;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -18,13 +18,14 @@ use serenity::{
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
use crate::{
 | 
					use crate::{
 | 
				
			||||||
    commands::{
 | 
					    commands::{
 | 
				
			||||||
 | 
					        moderation_cmds::{max_macro_page, show_macro_page},
 | 
				
			||||||
        reminder_cmds::{max_delete_page, show_delete_page},
 | 
					        reminder_cmds::{max_delete_page, show_delete_page},
 | 
				
			||||||
        todo_cmds::{max_todo_page, show_todo_page},
 | 
					        todo_cmds::{max_todo_page, show_todo_page},
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    component_models::pager::{DelPager, LookPager, Pager, TodoPager},
 | 
					    component_models::pager::{DelPager, LookPager, MacroPager, Pager, TodoPager},
 | 
				
			||||||
    consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
 | 
					    consts::{EMBED_DESCRIPTION_MAX_LENGTH, THEME_COLOR},
 | 
				
			||||||
    framework::CommandInvoke,
 | 
					    framework::CommandInvoke,
 | 
				
			||||||
    models::reminder::Reminder,
 | 
					    models::{command_macro::CommandMacro, reminder::Reminder},
 | 
				
			||||||
    SQLPool,
 | 
					    SQLPool,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -38,6 +39,7 @@ pub enum ComponentDataModel {
 | 
				
			|||||||
    TodoPager(TodoPager),
 | 
					    TodoPager(TodoPager),
 | 
				
			||||||
    DelSelector(DelSelector),
 | 
					    DelSelector(DelSelector),
 | 
				
			||||||
    TodoSelector(TodoSelector),
 | 
					    TodoSelector(TodoSelector),
 | 
				
			||||||
 | 
					    MacroPager(MacroPager),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
impl ComponentDataModel {
 | 
					impl ComponentDataModel {
 | 
				
			||||||
@@ -260,6 +262,17 @@ INSERT IGNORE INTO roles (role, name, guild_id) VALUES (?, \"Role\", (SELECT id
 | 
				
			|||||||
                let mut invoke = CommandInvoke::component(component);
 | 
					                let mut invoke = CommandInvoke::component(component);
 | 
				
			||||||
                let _ = invoke.respond(&ctx, resp).await;
 | 
					                let _ = invoke.respond(&ctx, resp).await;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            ComponentDataModel::MacroPager(pager) => {
 | 
				
			||||||
 | 
					                let mut invoke = CommandInvoke::component(component);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let macros = CommandMacro::from_guild(ctx, invoke.guild_id().unwrap()).await;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let max_page = max_macro_page(¯os);
 | 
				
			||||||
 | 
					                let page = pager.next_page(max_page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                let resp = show_macro_page(¯os, page);
 | 
				
			||||||
 | 
					                let _ = invoke.respond(&ctx, resp).await;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -330,3 +330,82 @@ impl TodoPager {
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Serialize, Deserialize)]
 | 
				
			||||||
 | 
					pub struct MacroPager {
 | 
				
			||||||
 | 
					    pub page: usize,
 | 
				
			||||||
 | 
					    action: PageAction,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Pager for MacroPager {
 | 
				
			||||||
 | 
					    fn next_page(&self, max_pages: usize) -> usize {
 | 
				
			||||||
 | 
					        match self.action {
 | 
				
			||||||
 | 
					            PageAction::First => 0,
 | 
				
			||||||
 | 
					            PageAction::Previous => 0.max(self.page - 1),
 | 
				
			||||||
 | 
					            PageAction::Refresh => self.page,
 | 
				
			||||||
 | 
					            PageAction::Next => (max_pages - 1).min(self.page + 1),
 | 
				
			||||||
 | 
					            PageAction::Last => max_pages - 1,
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    fn create_button_row(&self, max_pages: usize, comp: &mut CreateComponents) {
 | 
				
			||||||
 | 
					        let next_page = self.next_page(max_pages);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        let (page_first, page_prev, page_refresh, page_next, page_last) =
 | 
				
			||||||
 | 
					            MacroPager::buttons(next_page);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        comp.create_action_row(|row| {
 | 
				
			||||||
 | 
					            row.create_button(|b| {
 | 
				
			||||||
 | 
					                b.label("⏮️")
 | 
				
			||||||
 | 
					                    .style(ButtonStyle::Primary)
 | 
				
			||||||
 | 
					                    .custom_id(page_first.to_custom_id())
 | 
				
			||||||
 | 
					                    .disabled(next_page == 0)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .create_button(|b| {
 | 
				
			||||||
 | 
					                b.label("◀️")
 | 
				
			||||||
 | 
					                    .style(ButtonStyle::Secondary)
 | 
				
			||||||
 | 
					                    .custom_id(page_prev.to_custom_id())
 | 
				
			||||||
 | 
					                    .disabled(next_page == 0)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .create_button(|b| {
 | 
				
			||||||
 | 
					                b.label("🔁").style(ButtonStyle::Secondary).custom_id(page_refresh.to_custom_id())
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .create_button(|b| {
 | 
				
			||||||
 | 
					                b.label("▶️")
 | 
				
			||||||
 | 
					                    .style(ButtonStyle::Secondary)
 | 
				
			||||||
 | 
					                    .custom_id(page_next.to_custom_id())
 | 
				
			||||||
 | 
					                    .disabled(next_page + 1 == max_pages)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .create_button(|b| {
 | 
				
			||||||
 | 
					                b.label("⏭️")
 | 
				
			||||||
 | 
					                    .style(ButtonStyle::Primary)
 | 
				
			||||||
 | 
					                    .custom_id(page_last.to_custom_id())
 | 
				
			||||||
 | 
					                    .disabled(next_page + 1 == max_pages)
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl MacroPager {
 | 
				
			||||||
 | 
					    pub fn new(page: usize) -> Self {
 | 
				
			||||||
 | 
					        Self { page, action: PageAction::Refresh }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn buttons(
 | 
				
			||||||
 | 
					        page: usize,
 | 
				
			||||||
 | 
					    ) -> (
 | 
				
			||||||
 | 
					        ComponentDataModel,
 | 
				
			||||||
 | 
					        ComponentDataModel,
 | 
				
			||||||
 | 
					        ComponentDataModel,
 | 
				
			||||||
 | 
					        ComponentDataModel,
 | 
				
			||||||
 | 
					        ComponentDataModel,
 | 
				
			||||||
 | 
					    ) {
 | 
				
			||||||
 | 
					        (
 | 
				
			||||||
 | 
					            ComponentDataModel::MacroPager(MacroPager { page, action: PageAction::First }),
 | 
				
			||||||
 | 
					            ComponentDataModel::MacroPager(MacroPager { page, action: PageAction::Previous }),
 | 
				
			||||||
 | 
					            ComponentDataModel::MacroPager(MacroPager { page, action: PageAction::Refresh }),
 | 
				
			||||||
 | 
					            ComponentDataModel::MacroPager(MacroPager { page, action: PageAction::Next }),
 | 
				
			||||||
 | 
					            ComponentDataModel::MacroPager(MacroPager { page, action: PageAction::Last }),
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -243,9 +243,9 @@ impl CommandInvoke {
 | 
				
			|||||||
                    .map(|_| ())
 | 
					                    .map(|_| ())
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            InvokeModel::Component(i) => {
 | 
					            InvokeModel::Component(i) => i
 | 
				
			||||||
                if self.already_responded {
 | 
					                .create_interaction_response(http, |r| {
 | 
				
			||||||
                    i.create_followup_message(http, |d| {
 | 
					                    r.kind(InteractionResponseType::UpdateMessage).interaction_response_data(|d| {
 | 
				
			||||||
                        d.content(generic_response.content);
 | 
					                        d.content(generic_response.content);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if let Some(embed) = generic_response.embed {
 | 
					                        if let Some(embed) = generic_response.embed {
 | 
				
			||||||
@@ -261,51 +261,9 @@ impl CommandInvoke {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                        d
 | 
					                        d
 | 
				
			||||||
                    })
 | 
					                    })
 | 
				
			||||||
                    .await
 | 
					                })
 | 
				
			||||||
                    .map(|_| ())
 | 
					                .await
 | 
				
			||||||
                } else if self.deferred {
 | 
					                .map(|_| ()),
 | 
				
			||||||
                    i.edit_original_interaction_response(http, |d| {
 | 
					 | 
				
			||||||
                        d.content(generic_response.content);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if let Some(embed) = generic_response.embed {
 | 
					 | 
				
			||||||
                            d.add_embed(embed);
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        if let Some(components) = generic_response.components {
 | 
					 | 
				
			||||||
                            d.components(|c| {
 | 
					 | 
				
			||||||
                                *c = components;
 | 
					 | 
				
			||||||
                                c
 | 
					 | 
				
			||||||
                            });
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                        d
 | 
					 | 
				
			||||||
                    })
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
                    .map(|_| ())
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    i.create_interaction_response(http, |r| {
 | 
					 | 
				
			||||||
                        r.kind(InteractionResponseType::ChannelMessageWithSource)
 | 
					 | 
				
			||||||
                            .interaction_response_data(|d| {
 | 
					 | 
				
			||||||
                                d.content(generic_response.content);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                if let Some(embed) = generic_response.embed {
 | 
					 | 
				
			||||||
                                    d.add_embed(embed);
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                if let Some(components) = generic_response.components {
 | 
					 | 
				
			||||||
                                    d.components(|c| {
 | 
					 | 
				
			||||||
                                        *c = components;
 | 
					 | 
				
			||||||
                                        c
 | 
					 | 
				
			||||||
                                    });
 | 
					 | 
				
			||||||
                                }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                                d
 | 
					 | 
				
			||||||
                            })
 | 
					 | 
				
			||||||
                    })
 | 
					 | 
				
			||||||
                    .await
 | 
					 | 
				
			||||||
                    .map(|_| ())
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            InvokeModel::Text(m) => m
 | 
					            InvokeModel::Text(m) => m
 | 
				
			||||||
                .channel_id
 | 
					                .channel_id
 | 
				
			||||||
                .send_message(http, |m| {
 | 
					                .send_message(http, |m| {
 | 
				
			||||||
@@ -457,7 +415,12 @@ impl CommandOptions {
 | 
				
			|||||||
                    cmd_opts.options.insert(
 | 
					                    cmd_opts.options.insert(
 | 
				
			||||||
                        option.name,
 | 
					                        option.name,
 | 
				
			||||||
                        OptionValue::User(UserId(
 | 
					                        OptionValue::User(UserId(
 | 
				
			||||||
                            option.value.map(|m| m.as_u64()).flatten().unwrap(),
 | 
					                            option
 | 
				
			||||||
 | 
					                                .value
 | 
				
			||||||
 | 
					                                .map(|m| m.as_str().map(|s| s.parse::<u64>().ok()))
 | 
				
			||||||
 | 
					                                .flatten()
 | 
				
			||||||
 | 
					                                .flatten()
 | 
				
			||||||
 | 
					                                .unwrap(),
 | 
				
			||||||
                        )),
 | 
					                        )),
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
@@ -465,7 +428,12 @@ impl CommandOptions {
 | 
				
			|||||||
                    cmd_opts.options.insert(
 | 
					                    cmd_opts.options.insert(
 | 
				
			||||||
                        option.name,
 | 
					                        option.name,
 | 
				
			||||||
                        OptionValue::Channel(ChannelId(
 | 
					                        OptionValue::Channel(ChannelId(
 | 
				
			||||||
                            option.value.map(|m| m.as_u64()).flatten().unwrap(),
 | 
					                            option
 | 
				
			||||||
 | 
					                                .value
 | 
				
			||||||
 | 
					                                .map(|m| m.as_str().map(|s| s.parse::<u64>().ok()))
 | 
				
			||||||
 | 
					                                .flatten()
 | 
				
			||||||
 | 
					                                .flatten()
 | 
				
			||||||
 | 
					                                .unwrap(),
 | 
				
			||||||
                        )),
 | 
					                        )),
 | 
				
			||||||
                    );
 | 
					                    );
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -304,11 +304,6 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
 | 
				
			|||||||
        // reminder commands
 | 
					        // reminder commands
 | 
				
			||||||
        .add_command(&reminder_cmds::TIMER_COMMAND)
 | 
					        .add_command(&reminder_cmds::TIMER_COMMAND)
 | 
				
			||||||
        .add_command(&reminder_cmds::REMIND_COMMAND)
 | 
					        .add_command(&reminder_cmds::REMIND_COMMAND)
 | 
				
			||||||
        /*
 | 
					 | 
				
			||||||
        .add_command("natural", &reminder_cmds::NATURAL_COMMAND)
 | 
					 | 
				
			||||||
        .add_command("n", &reminder_cmds::NATURAL_COMMAND)
 | 
					 | 
				
			||||||
        .add_command("", &reminder_cmds::NATURAL_COMMAND)
 | 
					 | 
				
			||||||
        */
 | 
					 | 
				
			||||||
        // management commands
 | 
					        // management commands
 | 
				
			||||||
        .add_command(&reminder_cmds::DELETE_COMMAND)
 | 
					        .add_command(&reminder_cmds::DELETE_COMMAND)
 | 
				
			||||||
        .add_command(&reminder_cmds::LOOK_COMMAND)
 | 
					        .add_command(&reminder_cmds::LOOK_COMMAND)
 | 
				
			||||||
@@ -318,10 +313,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
 | 
				
			|||||||
        // to-do commands
 | 
					        // to-do commands
 | 
				
			||||||
        .add_command(&todo_cmds::TODO_COMMAND)
 | 
					        .add_command(&todo_cmds::TODO_COMMAND)
 | 
				
			||||||
        // moderation commands
 | 
					        // moderation commands
 | 
				
			||||||
        .add_command(&moderation_cmds::BLACKLIST_COMMAND)
 | 
					 | 
				
			||||||
        .add_command(&moderation_cmds::RESTRICT_COMMAND)
 | 
					        .add_command(&moderation_cmds::RESTRICT_COMMAND)
 | 
				
			||||||
        .add_command(&moderation_cmds::TIMEZONE_COMMAND)
 | 
					        .add_command(&moderation_cmds::TIMEZONE_COMMAND)
 | 
				
			||||||
        .add_command(&moderation_cmds::PREFIX_COMMAND)
 | 
					 | 
				
			||||||
        .add_command(&moderation_cmds::MACRO_CMD_COMMAND)
 | 
					        .add_command(&moderation_cmds::MACRO_CMD_COMMAND)
 | 
				
			||||||
        .add_hook(&hooks::CHECK_SELF_PERMISSIONS_HOOK)
 | 
					        .add_hook(&hooks::CHECK_SELF_PERMISSIONS_HOOK)
 | 
				
			||||||
        .add_hook(&hooks::MACRO_CHECK_HOOK)
 | 
					        .add_hook(&hooks::MACRO_CHECK_HOOK)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,3 @@
 | 
				
			|||||||
use regex::Captures;
 | 
					 | 
				
			||||||
use serenity::model::{channel::Message, guild::Guild, misc::Mentionable};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
use crate::{consts::REGEX_CONTENT_SUBSTITUTION, models::reminder::errors::ContentError};
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pub struct Content {
 | 
					pub struct Content {
 | 
				
			||||||
    pub content: String,
 | 
					    pub content: String,
 | 
				
			||||||
    pub tts: bool,
 | 
					    pub tts: bool,
 | 
				
			||||||
@@ -14,55 +9,4 @@ impl Content {
 | 
				
			|||||||
    pub fn new() -> Self {
 | 
					    pub fn new() -> Self {
 | 
				
			||||||
        Self { content: "".to_string(), tts: false, attachment: None, attachment_name: None }
 | 
					        Self { content: "".to_string(), tts: false, attachment: None, attachment_name: None }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub async fn build<S: ToString>(content: S, message: &Message) -> Result<Self, ContentError> {
 | 
					 | 
				
			||||||
        if message.attachments.len() > 1 {
 | 
					 | 
				
			||||||
            Err(ContentError::TooManyAttachments)
 | 
					 | 
				
			||||||
        } else if let Some(attachment) = message.attachments.get(0) {
 | 
					 | 
				
			||||||
            if attachment.size > 8_000_000 {
 | 
					 | 
				
			||||||
                Err(ContentError::AttachmentTooLarge)
 | 
					 | 
				
			||||||
            } else if let Ok(attachment_bytes) = attachment.download().await {
 | 
					 | 
				
			||||||
                Ok(Self {
 | 
					 | 
				
			||||||
                    content: content.to_string(),
 | 
					 | 
				
			||||||
                    tts: false,
 | 
					 | 
				
			||||||
                    attachment: Some(attachment_bytes),
 | 
					 | 
				
			||||||
                    attachment_name: Some(attachment.filename.clone()),
 | 
					 | 
				
			||||||
                })
 | 
					 | 
				
			||||||
            } else {
 | 
					 | 
				
			||||||
                Err(ContentError::AttachmentDownloadFailed)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        } else {
 | 
					 | 
				
			||||||
            Ok(Self {
 | 
					 | 
				
			||||||
                content: content.to_string(),
 | 
					 | 
				
			||||||
                tts: false,
 | 
					 | 
				
			||||||
                attachment: None,
 | 
					 | 
				
			||||||
                attachment_name: None,
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    pub fn substitute(&mut self, guild: Guild) {
 | 
					 | 
				
			||||||
        if self.content.starts_with("/tts ") {
 | 
					 | 
				
			||||||
            self.tts = true;
 | 
					 | 
				
			||||||
            self.content = self.content.split_off(5);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        self.content = REGEX_CONTENT_SUBSTITUTION
 | 
					 | 
				
			||||||
            .replace(&self.content, |caps: &Captures| {
 | 
					 | 
				
			||||||
                if let Some(user) = caps.name("user") {
 | 
					 | 
				
			||||||
                    format!("<@{}>", user.as_str())
 | 
					 | 
				
			||||||
                } else if let Some(role_name) = caps.name("role") {
 | 
					 | 
				
			||||||
                    if let Some(role) = guild.role_by_name(role_name.as_str()) {
 | 
					 | 
				
			||||||
                        role.mention().to_string()
 | 
					 | 
				
			||||||
                    } else {
 | 
					 | 
				
			||||||
                        format!("<<{}>>", role_name.as_str().to_string())
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    String::new()
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
            })
 | 
					 | 
				
			||||||
            .to_string()
 | 
					 | 
				
			||||||
            .replace("<<everyone>>", "@everyone")
 | 
					 | 
				
			||||||
            .replace("<<here>>", "@here");
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -7,8 +7,6 @@ pub enum ReminderError {
 | 
				
			|||||||
    PastTime,
 | 
					    PastTime,
 | 
				
			||||||
    ShortInterval,
 | 
					    ShortInterval,
 | 
				
			||||||
    InvalidTag,
 | 
					    InvalidTag,
 | 
				
			||||||
    InvalidTime,
 | 
					 | 
				
			||||||
    InvalidExpiration,
 | 
					 | 
				
			||||||
    DiscordError(String),
 | 
					    DiscordError(String),
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,31 +30,7 @@ impl ToString for ReminderError {
 | 
				
			|||||||
            ReminderError::InvalidTag => {
 | 
					            ReminderError::InvalidTag => {
 | 
				
			||||||
                "Couldn't find a location by your tag. Your tag must be either a channel or a user (not a role)".to_string()
 | 
					                "Couldn't find a location by your tag. Your tag must be either a channel or a user (not a role)".to_string()
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            ReminderError::InvalidTime => {
 | 
					 | 
				
			||||||
                "Your time failed to process. Please make it as clear as possible, for example `\"16th of july\"` or `\"in 20 minutes\"`".to_string()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            ReminderError::InvalidExpiration => {
 | 
					 | 
				
			||||||
                "Your expiration time failed to process. Please make it as clear as possible, for example `\"16th of july\"` or `\"in 20 minutes\"`".to_string()
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
            ReminderError::DiscordError(s) => format!("A Discord error occurred: **{}**", s),
 | 
					            ReminderError::DiscordError(s) => format!("A Discord error occurred: **{}**", s),
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
#[derive(Debug)]
 | 
					 | 
				
			||||||
pub enum ContentError {
 | 
					 | 
				
			||||||
    TooManyAttachments,
 | 
					 | 
				
			||||||
    AttachmentTooLarge,
 | 
					 | 
				
			||||||
    AttachmentDownloadFailed,
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
impl ToString for ContentError {
 | 
					 | 
				
			||||||
    fn to_string(&self) -> String {
 | 
					 | 
				
			||||||
        match self {
 | 
					 | 
				
			||||||
            ContentError::TooManyAttachments => "remind/too_many_attachments",
 | 
					 | 
				
			||||||
            ContentError::AttachmentTooLarge => "remind/attachment_too_large",
 | 
					 | 
				
			||||||
            ContentError::AttachmentDownloadFailed => "remind/attachment_download_failed",
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        .to_string()
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user