tulpje_framework/
interaction.rs1use twilight_model::{
2 application::interaction::{
3 InteractionData,
4 application_command::{CommandDataOption, CommandOptionValue},
5 },
6 gateway::payload::incoming::InteractionCreate,
7};
8
9use crate::{Error, Metadata, context};
10
11pub fn parse<T: Clone + Send + Sync>(
12 event: &InteractionCreate,
13 meta: Metadata,
14 ctx: context::Context<T>,
15) -> Result<context::InteractionContext<T>, Error> {
16 match &event.data {
17 Some(InteractionData::ApplicationCommand(command)) => {
18 let (name, options) = extract_command(&command.name, &command.options, &mut Vec::new());
19 Ok(context::InteractionContext::<T>::Command(
20 context::CommandContext::from_context(
21 meta,
22 ctx,
23 event.clone(),
24 *command.clone(),
25 name,
26 options,
27 ),
28 ))
29 }
30 Some(InteractionData::MessageComponent(interaction)) => {
31 Ok(context::InteractionContext::<T>::ComponentInteraction(
32 context::ComponentInteractionContext::from_context(
33 ctx,
34 meta,
35 event.clone(),
36 *interaction.clone(),
37 ),
38 ))
39 }
40 Some(InteractionData::ModalSubmit(data)) => Ok(context::InteractionContext::<T>::Modal(
41 context::ModalContext::from_context(ctx, meta, event.clone(), *data.clone()),
42 )),
43 Some(_) => Err(format!("unknown interaction type: {:?}", event.kind).into()),
44 None => Err("no interaction data".into()),
45 }
46}
47
48fn extract_command<'a>(
49 name: &'a str,
50 options: &'a [CommandDataOption],
51 parents: &mut Vec<&'a str>,
52) -> (String, &'a [CommandDataOption]) {
53 parents.push(name);
54
55 if let Some((name, options)) = options.iter().find_map(|opt| match opt.value {
56 CommandOptionValue::SubCommand(ref sub_options)
57 | CommandOptionValue::SubCommandGroup(ref sub_options) => Some((&opt.name, sub_options)),
58 _ => None,
59 }) {
60 extract_command(name, options, parents)
61 } else {
62 (parents.join(" "), options)
63 }
64}