From b328204e1c5aa7115d3397818aed5c8bc8e6b2d8 Mon Sep 17 00:00:00 2001 From: Jacherr Date: Tue, 24 Sep 2024 18:49:48 +0100 Subject: [PATCH] add experimental user command --- assyst-core/src/command/arguments.rs | 6 ++++++ assyst-core/src/command/fun/mod.rs | 2 +- assyst-core/src/command/fun/translation.rs | 2 +- assyst-core/src/command/group.rs | 6 ++++-- assyst-core/src/command/image/mod.rs | 2 +- assyst-core/src/command/misc/mod.rs | 8 ++++++-- assyst-core/src/command/misc/tag.rs | 3 ++- assyst-core/src/command/mod.rs | 7 +++++-- assyst-core/src/command/registry.rs | 16 ++++++++++++++-- assyst-core/src/command/services/mod.rs | 2 +- .../event_handlers/interaction_create.rs | 14 ++++++++++++-- .../event_handlers/message_create.rs | 1 + .../event_handlers/message_update.rs | 1 + assyst-core/src/rest/mod.rs | 2 +- assyst-proc-macro/src/lib.rs | 15 +++++++++++++-- 15 files changed, 69 insertions(+), 18 deletions(-) diff --git a/assyst-core/src/command/arguments.rs b/assyst-core/src/command/arguments.rs index 8667897..71c7019 100644 --- a/assyst-core/src/command/arguments.rs +++ b/assyst-core/src/command/arguments.rs @@ -417,6 +417,12 @@ impl ParseArgument for User { ctxt: &mut InteractionCommandParseCtxt<'_>, label: Label, ) -> Result { + if let Some(ref us) = &ctxt.cx.data.resolved_users + && let Some(u) = us.first() + { + return Ok(User(u.clone())); + } + let word = &ctxt.option_by_name(&label.unwrap().0)?.value; if let CommandOptionValue::User(id) = word { diff --git a/assyst-core/src/command/fun/mod.rs b/assyst-core/src/command/fun/mod.rs index f55cd48..189ccac 100644 --- a/assyst-core/src/command/fun/mod.rs +++ b/assyst-core/src/command/fun/mod.rs @@ -20,7 +20,7 @@ pub mod translation; usage = "[video]", examples = ["https://link.to.my/video.mp4"], send_processing = true, - context_menu_command = "Find Song" + context_menu_message_command = "Find Song" )] pub async fn findsong(ctxt: CommandCtxt<'_>, audio: ImageUrl) -> anyhow::Result<()> { const VALID_FILES: &[&str] = &["mp3", "mp4", "webm", "ogg", "wav"]; diff --git a/assyst-core/src/command/fun/translation.rs b/assyst-core/src/command/fun/translation.rs index 653f871..ca4ff18 100644 --- a/assyst-core/src/command/fun/translation.rs +++ b/assyst-core/src/command/fun/translation.rs @@ -99,7 +99,7 @@ impl ParseArgument for BadTranslateFlags { ("count", "Set the amount of translations to perform") ], send_processing = true, - context_menu_command = "Bad Translate" + context_menu_message_command = "Bad Translate" )] pub async fn bad_translate(ctxt: CommandCtxt<'_>, text: Rest, flags: BadTranslateFlags) -> anyhow::Result<()> { if text.0 == "languages" { diff --git a/assyst-core/src/command/group.rs b/assyst-core/src/command/group.rs index ab79db0..0476b56 100644 --- a/assyst-core/src/command/group.rs +++ b/assyst-core/src/command/group.rs @@ -24,7 +24,8 @@ macro_rules! defaults { (send_processing) => { false }; (guild_only $x:expr) => { $x }; (guild_only) => { false }; - (context_menu_command) => { "" }; + (context_menu_message_command) => { "" }; + (context_menu_user_command) => { "" }; } #[allow(clippy::crate_in_macro_def)] @@ -79,7 +80,8 @@ macro_rules! define_commandgroup { send_processing: $crate::defaults!(send_processing $($send_processing)?), guild_only: $crate::defaults!(guild_only $($guild_only)?), flag_descriptions: std::collections::HashMap::new(), - context_menu_command: $crate::defaults!(context_menu_command) + context_menu_message_command: $crate::defaults!(context_menu_message_command), + context_menu_user_command: $crate::defaults!(context_menu_user_command) }) } diff --git a/assyst-core/src/command/image/mod.rs b/assyst-core/src/command/image/mod.rs index 496e828..4e2e812 100644 --- a/assyst-core/src/command/image/mod.rs +++ b/assyst-core/src/command/image/mod.rs @@ -330,7 +330,7 @@ pub async fn grayscale(ctxt: CommandCtxt<'_>, source: Image) -> anyhow::Result<( usage = "[image]", examples = ["https://link.to.my/image.png"], send_processing = true, - context_menu_command = "Image Information" + context_menu_message_command = "Image Information" )] pub async fn imageinfo(ctxt: CommandCtxt<'_>, source: Image) -> anyhow::Result<()> { let result = ctxt.flux_handler().image_info(source.0).await?; diff --git a/assyst-core/src/command/misc/mod.rs b/assyst-core/src/command/misc/mod.rs index 232f770..4bb9f10 100644 --- a/assyst-core/src/command/misc/mod.rs +++ b/assyst-core/src/command/misc/mod.rs @@ -212,7 +212,7 @@ pub async fn patronstatus(ctxt: CommandCtxt<'_>) -> anyhow::Result<()> { }; ctxt.reply(format!( - "{}\n{}\n{}", + "{}\n{}\n{}\nIf something here doesn't look right, please ask in the {}.", match entitlement_status { Some(Some(e)) => format!("This server is an activated premium server. It was activated by <@{0}> ({0}).", e.user_id), Some(None) => format!( @@ -231,7 +231,11 @@ pub async fn patronstatus(ctxt: CommandCtxt<'_>) -> anyhow::Result<()> { .to_owned() } else { format!("You have {free_tier_2_requests} free tier 2 requests.") - } + }, + "official support server".codestring().url( + "", + Some("Invite link for the Assyst Support Discord Server.") + ) )) .await?; diff --git a/assyst-core/src/command/misc/tag.rs b/assyst-core/src/command/misc/tag.rs index f5a258d..de9ddc4 100644 --- a/assyst-core/src/command/misc/tag.rs +++ b/assyst-core/src/command/misc/tag.rs @@ -422,7 +422,8 @@ impl ParseArgument for TagListFlags { usage = "", examples = ["@jacher"], flag_descriptions = [("page ", "start at this page number")], - guild_only = true + guild_only = true, + context_menu_user_command = "List Owned Tags" )] pub async fn list(ctxt: CommandCtxt<'_>, user: Option, flags: TagListFlags) -> anyhow::Result<()> { let Some(guild_id) = ctxt.data.guild_id else { diff --git a/assyst-core/src/command/mod.rs b/assyst-core/src/command/mod.rs index 71627a1..7899cd7 100644 --- a/assyst-core/src/command/mod.rs +++ b/assyst-core/src/command/mod.rs @@ -106,7 +106,8 @@ pub struct CommandMetadata { pub send_processing: bool, pub age_restricted: bool, pub flag_descriptions: HashMap<&'static str, &'static str>, - pub context_menu_command: &'static str, + pub context_menu_message_command: &'static str, + pub context_menu_user_command: &'static str, pub guild_only: bool, } @@ -279,8 +280,10 @@ pub struct CommandData<'a> { pub interaction_id: Option>, pub interaction_attachments: HashMap, Attachment>, pub command_from_install_context: bool, - /// None if not a context menu command. + /// None if not a context menu message command. pub resolved_messages: Option>, + /// None if not a context menu user command. + pub resolved_users: Option>, } pub type RawMessageArgsIter<'a> = SplitAsciiWhitespace<'a>; diff --git a/assyst-core/src/command/registry.rs b/assyst-core/src/command/registry.rs index 33e59f1..9c198f3 100644 --- a/assyst-core/src/command/registry.rs +++ b/assyst-core/src/command/registry.rs @@ -134,7 +134,10 @@ pub fn find_command_by_name(name: &str) -> Option { .or_else(|| { get_or_init_commands() .iter() - .find(|x| x.1.metadata().context_menu_command == name) + .find(|x| { + let m = x.1.metadata(); + m.context_menu_message_command == name || m.context_menu_user_command == name + }) .map(|c| *c.1) }) } @@ -147,7 +150,7 @@ pub async fn register_interaction_commands(assyst: ThreadSafeAssyst) -> anyhow:: let i = x.1.as_interaction_command(); let m = x.1.metadata(); if !i.name.is_empty() { - Some((i, m.context_menu_command)) + Some((i, m.context_menu_message_command, m.context_menu_user_command)) } else { None } @@ -159,12 +162,21 @@ pub async fn register_interaction_commands(assyst: ThreadSafeAssyst) -> anyhow:: for command in interaction_commands { if !deduplicated_commands.iter().any(|x| x.name == command.0.name) { if !command.1.is_empty() { + // context message command let mut copy = command.0.clone(); copy.name = command.1.to_owned(); copy.kind = CommandType::Message; copy.options = vec![]; copy.description = String::new(); deduplicated_commands.push(copy); + } else if !command.2.is_empty() { + // context user command + let mut copy = command.0.clone(); + copy.name = command.1.to_owned(); + copy.kind = CommandType::User; + copy.options = vec![]; + copy.description = String::new(); + deduplicated_commands.push(copy); } deduplicated_commands.push(command.0); } diff --git a/assyst-core/src/command/services/mod.rs b/assyst-core/src/command/services/mod.rs index 0372d6d..0afaece 100644 --- a/assyst-core/src/command/services/mod.rs +++ b/assyst-core/src/command/services/mod.rs @@ -20,7 +20,7 @@ pub mod download; usage = "[text]", examples = ["yep im burning"], send_processing = true, - context_menu_command = "Burn Text" + context_menu_message_command = "Burn Text" )] pub async fn burntext(ctxt: CommandCtxt<'_>, text: Rest) -> anyhow::Result<()> { let result = burn_text(&text.0).await?; diff --git a/assyst-core/src/gateway_handler/event_handlers/interaction_create.rs b/assyst-core/src/gateway_handler/event_handlers/interaction_create.rs index 26d397b..7f9ebe3 100644 --- a/assyst-core/src/gateway_handler/event_handlers/interaction_create.rs +++ b/assyst-core/src/gateway_handler/event_handlers/interaction_create.rs @@ -13,6 +13,7 @@ use twilight_model::application::interaction::{InteractionContextType, Interacti use twilight_model::channel::Message; use twilight_model::gateway::payload::incoming::InteractionCreate; use twilight_model::http::interaction::{InteractionResponse, InteractionResponseType}; +use twilight_model::user::User; use twilight_model::util::Timestamp; use twilight_util::builder::InteractionResponseDataBuilder; @@ -146,14 +147,22 @@ pub async fn handle(assyst: ThreadSafeAssyst, InteractionCreate(interaction): In .map(|x| x.attachments) .unwrap_or(HashMap::new()); - // resolve message attachments for context menu commands + // resolve messages for context menu message commands let mut resolved_messages: Option> = None; - if let Some(ref ms) = command_data.resolved.map(|x| x.messages) + if let Some(ms) = command_data.resolved.as_ref().map(|x| &x.messages) && command_data.kind == CommandType::Message { resolved_messages = Some(ms.values().cloned().collect()); } + // resolve users for context menu user commands + let mut resolved_users: Option> = None; + if let Some(ref us) = command_data.resolved.map(|x| x.users) + && command_data.kind == CommandType::User + { + resolved_users = Some(us.values().cloned().collect()); + } + let data = CommandData { source: Source::Interaction, assyst: &assyst, @@ -178,6 +187,7 @@ pub async fn handle(assyst: ThreadSafeAssyst, InteractionCreate(interaction): In None => false, }, resolved_messages, + resolved_users, }; let ctxt = InteractionCommandParseCtxt::new(CommandCtxt::new(&data), &sorted_incoming_options); diff --git a/assyst-core/src/gateway_handler/event_handlers/message_create.rs b/assyst-core/src/gateway_handler/event_handlers/message_create.rs index 5ae910c..e952cc8 100644 --- a/assyst-core/src/gateway_handler/event_handlers/message_create.rs +++ b/assyst-core/src/gateway_handler/event_handlers/message_create.rs @@ -47,6 +47,7 @@ pub async fn handle(assyst: ThreadSafeAssyst, MessageCreate(message): MessageCre interaction_attachments: HashMap::new(), command_from_install_context: false, resolved_messages: None, + resolved_users: None, }; let ctxt = RawMessageParseCtxt::new(CommandCtxt::new(&data), result.args); diff --git a/assyst-core/src/gateway_handler/event_handlers/message_update.rs b/assyst-core/src/gateway_handler/event_handlers/message_update.rs index 1bd1132..5a5e0c6 100644 --- a/assyst-core/src/gateway_handler/event_handlers/message_update.rs +++ b/assyst-core/src/gateway_handler/event_handlers/message_update.rs @@ -47,6 +47,7 @@ pub async fn handle(assyst: ThreadSafeAssyst, event: MessageUpdate) { interaction_attachments: HashMap::new(), command_from_install_context: false, resolved_messages: None, + resolved_users: None, }; let ctxt = RawMessageParseCtxt::new(CommandCtxt::new(&data), result.args); diff --git a/assyst-core/src/rest/mod.rs b/assyst-core/src/rest/mod.rs index fe51275..d5266cd 100644 --- a/assyst-core/src/rest/mod.rs +++ b/assyst-core/src/rest/mod.rs @@ -12,6 +12,6 @@ pub mod rust; pub mod top_gg; pub mod web_media_download; -pub static NORMAL_DISCORD_UPLOAD_LIMIT_BYTES: u64 = 25_000_000; +pub static NORMAL_DISCORD_UPLOAD_LIMIT_BYTES: u64 = 10_000_000; pub static PREMIUM_TIER2_DISCORD_UPLOAD_LIMIT_BYTES: u64 = 50_000_000; pub static PREMIUM_TIER3_DISCORD_UPLOAD_LIMIT_BYTES: u64 = 100_000_000; diff --git a/assyst-proc-macro/src/lib.rs b/assyst-proc-macro/src/lib.rs index 17dd5f2..2e72a10 100644 --- a/assyst-proc-macro/src/lib.rs +++ b/assyst-proc-macro/src/lib.rs @@ -188,7 +188,17 @@ pub fn command(attrs: TokenStream, func: TokenStream) -> TokenStream { }); let send_processing = fields.remove("send_processing").unwrap_or_else(false_expr); let age_restricted = fields.remove("age_restricted").unwrap_or_else(false_expr); - let context_menu_command = fields.remove("context_menu_command").unwrap_or_else(|| str_expr("")); + let context_menu_message_command = fields + .remove("context_menu_message_command") + .unwrap_or_else(|| str_expr("")); + let context_menu_user_command = fields + .remove("context_menu_user_command") + .unwrap_or_else(|| str_expr("")); + + if context_menu_message_command != str_expr("") && context_menu_user_command != str_expr("") { + panic!("command cannot be a context message and user command at the same time"); + } + let flag_descriptions = fields.remove("flag_descriptions").unwrap_or_else(empty_array_expr); let guild_only = fields.remove("guild_only").unwrap_or_else(false_expr); @@ -218,7 +228,8 @@ pub fn command(attrs: TokenStream, func: TokenStream) -> TokenStream { send_processing: #send_processing, age_restricted: #age_restricted, flag_descriptions: descriptions, - context_menu_command: #context_menu_command, + context_menu_message_command: #context_menu_message_command, + context_menu_user_command: #context_menu_user_command, guild_only: #guild_only }) }