Creating custom commands (Akas)

Limnoria allows you create custom bot commands, also known as aliases, without writing a full Python plugin. This feature is provided by the Aka plugin, and can be combined with nested commands to create expressive commands.

Before proceeding through this page, we recommend reading the Command parsing primer, which discusses many of the details that apply to building custom commands.

Creating & managing aliases

Add an alias, trout, which expects one argument ($1). This alias requires the Reply plugin to be loaded since it provides the action command:

<jamessan> @aka add trout "reply action slaps $1 with a large trout"
<Limnoria> The operation succeeded.
# $1 will be replaced with the input to @trout
<jamessan> @trout me
* Limnoria slaps me with a large trout

You can also replace an existing alias with aka set:

<jlu5> @aka set trout "reply Sorry, we're all out of fish!"
<Limnoria> The operation succeeded.

To remove an alias, use aka remove:

<jlu5> @aka remove trout
<Limnoria> The operation succeeded.

Alias with nested commands

Add an alias, randpercent, which returns a random percentage value. This requires the Filter and Games plugins for squish and dice respetively:

<jlu5> @aka add randpercent "squish [dice 1d100]%"
<Limnoria> The operation succeeded.
<jlu5> @randpercent
<Limnoria> 66%

Note

When defining aliases, you almost always want to quote the contents of the alias, so that any nested commands are expanded when the actual alias is ran, instead of when the aka add call happens.

In this above example, not quoting the dice command would mean that the randpercent always returns the same value!

This, in conjunction with Limnoria’s command quoting rules means that aliases towards nested commands may require two levels of quoting, with the inner quotes additionally escaped. This example uses the sample command from the Utilities plugin:

<jlu5> @aka add greetme "reply [sample 1 \"hi there!\" \"what's up?\" \"how are you?\"]"
<Limnoria> The operation succeeded.
<jlu5> @greetme
<Limnoria> jlu5: what's up?
<jlu5> @greetme
<Limnoria> jlu5: hi there!

Passing multiple arguments

Aliases can pass multiple arguments ($1, $2, etc.), as well as all remaining arguments ($*) to another command. A common use case of this is to define short-forms to other commands, such as config:

<jlu5> @aka add cf "config $*"
<Limnoria> The operation succeeded.

# using this alias
<jlu5> @cf reply.whenaddressedby.chars
<Limnoria> @

Note that the following also works, because config is technically ambiguous (it can refer to either the Config plugin or the config command):

# "@cf help" expands to "@config help"
<jlu5> @cf help reply.whenaddressedby.chars
<Limnoria> Determines what prefix characters the bot will reply to. -snip-

Conditionals and optional arguments

Aliases also support optional arguments, using @1, @2, etc. instead of $1 and $2. This can be combined with the Conditional plugin to make a custom command behave differently depending on how many arguments were passed in.

Here’s a variant of the trout example from earlier, which will now slap the caller if no argument was passed in. It uses:

<jlu5> @aka add trout "reply action slaps [cif [ceq \"@1\" \"\"] \"echo $nick\" \"echo @1\"] with a large trout"
<Limnoria> The operation succeeded.
<jlu5> @trout Limnoria
* Limnoria slaps Limnoria with a large trout
<jlu5> @trout
* Limnoria slaps jlu5 with a large trout

Referring to other Akas

Because command aliases are expanded at runtime, they can refer to one another, and even themselves.

Suppose I define an alias for the sample command:

<jlu5> @aka add choose "sample 1 $*"
<Limnoria> The operation succeeded.

Then I can define more aliases using the choose command:

<jlu5> @aka add bloom "choose 🌼 💐 🌹 🌻 🌺 🌸"
<Limnoria> The operation succeeded.
<jlu5> @bloom
<Limnoria> 💐

For completeness, here’s an example of a (not particularly efficient) factorial command. It additionally uses the Math plugin’s calc command:

<jlu5> @aka add factorial "cif [nle $1 1] \"echo 1\" \"calc [factorial [calc $1 - 1]] * $1\""
<Limnoria> The operation succeeded.
<jlu5> @factorial 8
<Limnoria> 40320
<jlu5> @factorial 10
<Limnoria> Error: You've attempted more nesting than is currently allowed on this bot.

Replacing an existing command with your own

Using the defaultplugin command, it is possible to “replace” an existing command in the bot by defining an alias with the same name and running:

@defaultplugin <command> Aka

As an example, you can replace the default ping reply from the Misc plugin with a silly response:

<jlu5> @aka add ping "reply I don't respond to ping requests."
<Limnoria> The operation succeeded.
<jlu5> @defaultplugin ping Aka
<Limnoria> The operation succeeded.
<jlu5> @ping
<Limnoria> jlu5: I don't respond to ping requests.

The old command will still be accessible via its full name:

<jlu5> @misc ping
<Limnoria> pong

If you want to remove access for a command entirely, you should configure default capabilities instead.

Limitations, and when to write a plugin

Aliases and nested commands are not designed to replace plugins in all cases. If you need any of the following, it’s probably easier to write a custom plugin instead:

  • Persistent state (databases, etc.)

  • For, while loops

  • Access to web APIs or external Python libraries

  • Fine-grained permission checks

  • Threads / processes for slow or long-running tasks

Final notes

  • Capabilities apply to aliases as well as the commands they call. To run an alias successfully, a caller needs to have access to all commands called by the alias as well - keep this in mind if you declare a strict set of default capabilities.