use poise::serenity_prelude::model::{ application::interaction::application_command::CommandDataOption, id::GuildId, }; use serde::{Deserialize, Serialize}; use serde_json::Value; use crate::{Context, Data, Error}; type Func = for<'a> fn( poise::ApplicationContext<'a, U, E>, ) -> poise::BoxFuture<'a, Result<(), poise::FrameworkError<'a, U, E>>>; fn default_none() -> Option> { None } #[derive(Serialize, Deserialize)] pub struct RecordedCommand { #[serde(skip)] #[serde(default = "default_none::")] pub action: Option>, pub command_name: String, pub options: Vec, } pub struct CommandMacro { pub guild_id: GuildId, pub name: String, pub description: Option, pub commands: Vec>, } pub struct RawCommandMacro { pub guild_id: GuildId, pub name: String, pub description: Option, pub commands: Value, } pub async fn guild_command_macro( ctx: &Context<'_>, name: &str, ) -> Option> { let row = sqlx::query!( " SELECT * FROM macro WHERE guild_id = (SELECT id FROM guilds WHERE guild = ?) AND name = ? ", ctx.guild_id().unwrap().0, name ) .fetch_one(&ctx.data().database) .await .ok()?; let mut commands: Vec> = serde_json::from_str(&row.commands).unwrap(); for recorded_command in &mut commands { let command = &ctx .framework() .options() .commands .iter() .find(|c| c.identifying_name == recorded_command.command_name); recorded_command.action = command.map(|c| c.slash_action).flatten(); } let command_macro = CommandMacro { guild_id: ctx.guild_id().unwrap(), name: row.name, description: row.description, commands, }; Some(command_macro) }