use lazy_regex::regex; use poise::serenity_prelude::command::CommandOptionType; use regex::Captures; use serde_json::{json, Value}; use crate::{models::command_macro::RawCommandMacro, Context, Error, GuildId}; struct Alias { name: String, command: String, } /// Migrate old $alias reminder commands to macros. Only macro names that are not taken will be used. #[poise::command( slash_command, rename = "migrate", guild_only = true, default_member_permissions = "MANAGE_GUILD", identifying_name = "migrate_macro" )] pub async fn migrate_macro(ctx: Context<'_>) -> Result<(), Error> { let guild_id = ctx.guild_id().unwrap(); let mut transaction = ctx.data().database.begin().await?; let aliases = sqlx::query_as!( Alias, "SELECT name, command FROM command_aliases WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?)", guild_id.0 ) .fetch_all(&mut *transaction) .await?; let mut added_aliases = 0; for alias in aliases { match parse_text_command(guild_id, alias.name, &alias.command) { Some(cmd_macro) => { sqlx::query!( "INSERT INTO macro (guild_id, name, description, commands) VALUES ((SELECT id FROM guilds WHERE guild = ?), ?, ?, ?)", cmd_macro.guild_id.0, cmd_macro.name, cmd_macro.description, cmd_macro.commands ) .execute(&mut *transaction) .await?; added_aliases += 1; } None => {} } } transaction.commit().await?; ctx.send(|b| b.content(format!("Added {} macros.", added_aliases))).await?; Ok(()) } fn parse_text_command( guild_id: GuildId, alias_name: String, command: &str, ) -> Option { match command.split_once(" ") { Some((command_word, args)) => { let command_word = command_word.to_lowercase(); if command_word == "r" || command_word == "i" || command_word == "remind" || command_word == "interval" { let matcher = regex!( r#"(?P(?:<@\d+>\s+|<@!\d+>\s+|<#\d+>\s+)*)(?P