Skip to content

Mastering Velen Options

Mihou edited this page Nov 24, 2021 · 3 revisions

🗡️ Mastering Velen Options

Velen 3.0.0 was like a landslide to the Velenscape, bringing in major changes and among those changes was a brand new way of creating options, commands, and grabbing those options. For the entire duration of this wiki page, we'll be using Velen Mirror to construct our commands instead of the legacy command builder method.

To first understand how everything works, it is highly recommended that you read how Velen Mirror works and can be created. Press here to read about Velen Mirror

🏟️ The Option Structure

There are a total of five structures on Velen Mirror: command structure, category structure, subcommand structure, subcommand group structure and option structure, and in this wiki page, we'll be tackling the following subcommand structure, subcommand group structure and option structure and how to retrieve the arguments with message and hybrid handlers.

To first understand this entire thing, let us take a look at how all three structures look.

🥇 Subcommand Group & Subcommand Structure

We'll tackle these two structures first as the two structures are actually the same mold, in that they can only contain two types of values and those two are: option (for subcommand), subcommand (for subcommand group) and desc (for both). A full example of a subcommand would be:

# You can replace group with any name.
&[group]: subcommand_group {
   desc: This is a subcommand group.
   
   &[twoOptions]: subcommand {
      desc: This is a subcommand.
      &[optionOne]: option {
         type: string
         desc: This is an option.
      }

      &[optionTwo]: option {
         type: string
         desc: This is an option.
      }
   }

   &[oneOption]: subcommand {
      desc: This is a subcommand.
      &[optionOne]: option {
         type: string
         desc: This is an option.
      }
   }
}

Now that you've seen a full example of a subcommand group, a subcommand, and several options. How about we explain everything scope by scope, let us start with the subcommand group and subcommand.

A subcommand and subcommand group, as mentioned earlier, can only contain two values. For a subcommand, it can contain a description and the options that it will have whilst a subcommand group can only contain the description and its subcommands. The entire structure practically looks like this:

&[the name of the subcommand group here]: subcommand_group {
   desc: string
   [place your subcommands here]
}
&[the name of the subcommand]: subcommand {
   desc: string
   [place your options here]
}

It sounds so simple right, now let us move to the options structure which is considered as one of the most important structures in the new Velen Mirror and would most likely be the one that you have the most in your commands.

📦 Option Structure

To understand Options, let us first take a look at all the possible values of an option:

# This is how you specify the name of an option.
&[option name]: option {

   # This is the description of your option which will be
   # shown to your slash command.
   desc: string

   # This is the type of the option, to list them all:
   # user, channel, role, numeric, boolean, mentionable, number, integer : These will all convert to their slash command equivalent.
   # user, channel, role, message, emoji, webhook, boolean, numeric, integer, string: These will all convert to string on slash command
   # but the second line of types will be aliased to their regex pattern (or algorithm) for message commands.
   type: option_type

   # You can use this field to specify the regex pattern to be used for an option.
   # This only applies to message commands at the moment.
   regex: regex_pattern

   # This can be placed on the last option of a command
   # to tell Velen to grab all the remaining input of the user and squash
   # it into this option, for example, Hello World would be returned
   # if this option is enabled instead of just Hello
   # but you can also replicate this behavior by telling the user to wrap their input
   # in quotes like: "Hello World"
   has_many: boolean

   # This is how we make a slash command option required.
   # Options that the user does not input will be omitted for message commands.
   required: boolean

   # This is how you initialize or enforce choices into both slash and message commands (respectively).
   choice: [array of two]
}

I think that should have explained everything, right? How about we move to fetching arguments in both hybrid and message commands?

🈂️ Fetching Arguments

There are multiple ways to fetch arguments in both hybrid and message commands, slash commands is not included in this guide as slash commands always has only one way of fetching arguments and that is the default Javacord method. We'll be going through both hybrid and message arguments in this guide.

🥮 Hybrid Command

To start, how about we go with the handlers on the ping command on the examples folder? Press here to see the command structure

As the structure of the command only has one option, and the command simply uses that option as a response, all we need to do is fetch the option using its name which is response and flat map (basically squash an Optional with another Optional) to a String and checking if the option is present and responding. In code, it looks like this:

velen.addHandler("hybrid.ping", (event, responder, user, args) -> {
   args.withName("response").flatMap(VelenOption::asString).ifPresent(s -> responder.setContent(s).respond());
});

To fetch arguments in hybrid commands, it is HIGHLY RECOMMENDED to use the args variable which handles argument fetching for both slash and message commands for you... but if you wish to handle either, you may check the event variable which has everything you need.

🌑 Message Commands

Message commands also have a similar syntax but is more straightforward than Hybrid as you don't have to flat-map everything. We'll be using the equivalent command written on examples but rewritten for message commands for this example. You can veiw the example here.

As the structure of the command only has one option, and the command simply uses that option as a response, all we need to do is fetch the option using its name which is response and check whether it is present and respond. In code, it looks like this:

velen.addHandler("message.ping", (event, message, user, args, options) -> options.withName("response")
                .ifPresent(message::reply));