Written by Zephy, Gerard, xRappy, Veld
Sat Feb 22 2020
MiScript is Miki's custom command language, specifically written to make easy-to-use custom commands for your own server.
Not only are Miki's custom commands powerful, but they will also become real slash commands in your server, and will appear when you type /
.
In this guide, we will show you how to get started with MiScript.
Commands | Description |
---|---|
/customcommand create [command name] [script] | Used to create a custom command |
/customcommand remove [command name] | Used to delete an existing custom command |
/customcommand get [command name] | Used to get the code of an existing custom command |
/customcommand getstorage | Used to see the storage of custom commands |
/customcommand list | Used to see all custom commands in your server |
/customcommand sync | Used when something is wrong with your custom slash commands. |
/customcommand setdescription [command name] [description] | Used to set a description for your custom slash command. |
say("hello world!")
As you may have realized, this command simply makes Miki say "hello world". There's nothing else happening. You may add it to your server like this:
/customcommand create command-name:helloworld command-script:say("hello world!")
Variables let you store a value, and then use it later. You define them with var
and give it any name you want. For example:
var mynumber = 5
mynumber = mynumber * 2
say(mynumber)
This will create a variable called mynumber
with a value of 5. It will then multiply it by 2 and send it:
10
You can add a value to your text by putting it inside $[]
. For example:
say("The number is $[mynumber]")
Also, Miki will provide a few global variables you can use, such as author
, guild
, channel
and message
. These have information about how the command was used. Consider this example:
say("Hello $[author]")
If the user Veld used this command, it would send:
Hello Veld
You are able to send different responses under different conditions. For example:
if author = "Veld" then
say("Hello Veld!")
else
say("Wait, you're not Veld!")
end
The person using your command may include additional information. This is accessible through the global variable args
.
Imagine we have a command /age
, and its code is as follows:
say("You are $[args] years old")
If your user types /age 20
, Miki will say
You are 20 years old
However, if the user doesn't enter any args, its value will be empty. You may want to check like this:
if args.length == 0 then
say("No args!")
else
say(args)
end
The length in this case is the amount of arguments (which were separated by spaces), as args
is in fact a list. More on lists later.
It is also possible to send embeds with MiScript. You may even use them in /levelupmessage
. For example:
say(embed("Probably because you said something weird...")
.title("$[author.name] ignores you")
.image("https://media.giphy.com/media/H9jrEhsr1pUMo/giphy.gif"))
This would show:
There are more functions like .footer("Text")
and .color("red")
for the embed builder; check out the API reference for embeds.
In the "hello world" example, you saw how to add a command with a script to your server. However, sometimes your command consists of multiple lines, which currently can't be sent properly in a Discord slash command. In this case, you may chain lines together, and use ;
between each statement. Or you may use the non-slash command, like this:
Notice the dark background behind the code. This is a code block, and you may use it by putting triple backticks ``` at the start and end of your code. It is optional, but it makes it look more organized.
To remove an existing command, you can use /customcommand remove [command name]
. For example, if you want to remove the command we created above, you would use /customcommand remove orchid
.
The following sections will go in depth on what MiScript can do. This can be overwhelming when you're new to programming. If you need help, feel free to join our Discord Server and ask for help in the #miscript channel.
When you want to execute code multiple times, you can create a function.
The following code creates a function in MiScript:
fun greet(name)
say("Hello $[name]!")
end
Let's go through this script:
Code | Description |
---|---|
fun |
Tell MiScript that we'll create a new function. |
greet |
Function name. Use this name to call the function. |
(name) |
Arguments that the function takes. |
say("Hello $[name]!") |
The body of the function. This will be executed when the function is called. |
end |
End of the function |
Now that we defined the function "greet", we can call it:
greet("Veld")
This will return:
Hello Veld
Using functions, we can run code many times without having to copy and paste it. There is no "loop" statement in MiScript, but you may .map
over a range of numbers or a list of values. For example:
(1..10).map(fun(e)
say("I have said this $[e] times")
end)
Sometimes you don't want to define a whole function, just run a single line of code. This is possible with arrow functions.
Consider this example that takes a list of strings (text), and then converts every value into uppercase:
["hello", "miki"].map(e => e.upper())
Let's go through the arrow function:
Code | Description |
---|---|
e |
The parameter of the function. For more than one parameter, you can do (param1, param2) |
=> |
Tell MiScript we're creating an arrow function. |
e.upper() |
The body of the function, which is being directly returned. In this case, .upper() will uppercase every character. |
When you execute the code, the result will be: ["HELLO", "MIKI"]
. You will have to use say
to send it though.
Lists are used to store multiple values in a single variable. Normally, you would try to do this:
var user1 = "Veld"
var user2 = "Gerard"
var user3 = "Zephy"
say("Cool dudes: $[user1], $[user2], $[user3]")
You can see how the amount of variables will pile up if we add more users, and there is no easy way to get all the users at once. The solution is to use a list.
A list starts with [
and ends with ]
. So an empty list would be []
.
To create an list with a string, you place the string between the brackets: [ "value" ]
.
To add multiple strings, you add them separated with commas within the brackets: [ "Veld", "Gerard", "Zephy"]
.
There are several useful functions for lists, such as .map()
which we saw before.
We can join these users together with .join()
:
var users = ["Veld", "Gerard", "Zephy"]
say("Cool dudes: $[users.join(", ")]")
This will return:
Cool dudes: Veld, Gerard, Zephy
For more list functions check out the API reference for list.
Since there is a message limit on Discord, using if
and else
over and over again is not a good idea for bigger commands. Using stop
will stop the script and won't execute the rest of the code.
say("This message will be shown!")
stop
say("However, this message will be ignored!")
When a script is finished, all the variables you have defined will be lost. To save a value, you can use the storage API.
⚠ Warning: The storage API is not infallible; it's rarely possible that your data will be lost. We will work to prevent this from happening.
Let's create a command that remembers how many times the command was executed. First, decide a unique key that you'll use in the storage, in this example we'll be using "count"
.
To store a value in the storage, you can use storage.set()
.
storage.set("count", 1)
To retrieve a value from the storage, you can use storage.get()
.
When a key doesn't exist in the storage, the result will be null.
var count = storage.get("count")
Let's make a command that counts how many times it was executed.
First, we retrieve the value from the storage because it's possible that the command was executed before. When it doesn't exist, we set the count to 0.
var count = storage.get("count")
if not count then
count = 0
end
Now we increment the value by 1, store it back to the storage and say the result:
count = count + 1
storage.set("count", count)
say("Count: $[count]")
When executing the command multiple times, you'll see that the counter increases:
To see what data is stored in the storage, you can use the command /customcommand getstorage
:
To prevent abuse of the storage API, it has a key and value limit. To increase the amount of data, The owner of the Discord Server (where the command is being executed) can donate to get additional keys.
Default | Donator | |
---|---|---|
Amount of keys | 1 | 25 |
Maximum value size | 4 KB | 4 KB |
The following section covers what the API can do in MiScript.
Function | Description |
---|---|
args |
List with the arguments for the current message. Message: /command test Result: ["test"] |
message |
Current message. See Message for more information. |
author |
Author of the message. See User for more information. |
guild |
Current guild. See Guild for more information. |
channel |
Channel where the message was sent. See Channel for more information. |
storage |
Storage API. See Storage for more information. |
embed() |
Create a new embed. See Embed for more information. |
say(content) |
Send a message or embed. Example: say(embed("Hello world")) |
Function | Description |
---|---|
id |
Discord message ID. Example: message.id Result: 322845087467962368 |
content |
Content of the message. Example: message.content Result: "Hello!" |
Function | Description |
---|---|
id |
Discord guild ID. Example: guild.id Result: 160067691783127041 |
members |
Amount of members in the guild. Example: guild.members Result: 1337 |
icon |
Icon of the server. Example: guild.icon Result: "https://cdn.discordapp.com/icons/..." |
owner |
Owner of the server. See User for more information. |
Function | Description |
---|---|
id |
Discord channel ID. Example: channel.id Result: 160105994217586689 |
name |
Name of the channel. Example: channel.name Result: "general" |
nsfw |
True if the channel is NSFW. Example: channel.nsfw Result: false |
Function | Description |
---|---|
id |
Discord user ID. Example: user.id Result: 160067691783127041 |
bot |
True if the user is a bot. Example: user.bot Result: false |
mention |
Create a mention to the user. Example: user.mention Result: "<@160105994217586689>" |
discrim |
Discriminator of the user. Example: user.discrim Result: "6045" |
name |
Name of the user. Example: user.name Result: "Miki" |
Function | Description |
---|---|
.length |
Length of the string. Example: "miki".length Result: 4 |
.upper() |
Converts a string to uppercase letters. Example: "miki".upper() Result: "MIKI" |
.lower() |
Converts a string to lowercase letters. Example: "MIKI".lower() Result: "miki" |
.has(str) |
Check if the string contains a substring. Example: "Hello Miki".has("Miki") Result: true |
.startsWith(str) |
Check if the string starts with a substring. Example: "Hello Miki".startsWith("Hello") Result: true |
.endsWith(str) |
Check if the string ends with a substring. Example: "Hello Miki".endsWith("Miki") Result: true |
.replace(old, new) |
Replace every occurence of the old string with the new string. Example: "Hello Beld".replace("Beld", "Veld") Result: "Hello Veld" |
.trim() |
Remove every whitespace character at the begin and end of the string. Example: " Hello Miki ".trim() Result: "Hello Miki" |
.split() |
Splits the string into an list of substrings using every whitespace character. Example: "hello world".split() Result: ["hello", "world"] |
.split(seperator) |
Splits the string into an alistrray of substrings using the given seperator. Example: "hello-world".split("-") Result: ["hello", "world"] |
.indexOf(str) |
Get the position of the substring in the string. Example: "Hello Miki".indexOf("Miki") Result: 6 |
.remove(index, length) |
Remove a range in the string. Example: "Hello Miki".remove(0, 6) Result: "Miki" |
Function | Description |
---|---|
.toFixed(length) |
Converts the number into a string with the fixed amount of decimals. Example: (1.23456).toFixed(2) Result: "1.23" |
Function | Description |
---|---|
.length |
Amount of items in the list. Example: ["hello", "world"].length Result: 2 |
.has(item) |
Check if the list contains the item. Example: ["hello", "world"].has("hello") Result: true |
.add(item) |
Add a new item to the list. Example: ["hello"].add("world") Result: ["hello", "world"] |
.del(item) |
Removes am item from the list. Example: ["hello", "world"].del("world") Result: ["hello"] |
.join(seperator) |
Combine all the values into a single string with a separator. Example: ["hello", "world"].join(" ") Result: "hello world" |
.map(function) |
Create a new list and map all the values by calling the function. Example: ["hello", "world"].map(i => i.upper()) Result: ["HELLO", "WORLD"] |
.filter(function) |
Create a new list and add the values that pass the function filter. Example: ["hello", "world"].filter(i => i = "hello") Result: ["hello"] |
.take(amount) |
Create a new list and insert the first X amount of values. Example: ["hello", "world"].take(1) Result: ["hello"] |
.skip(amount) |
Create a new list and remove the first X amount of values. Example: ["hello", "world"].skip(1) Result: ["world"] |
.reverse() |
Create a new list and reverse the order of the items. Example: ["hello", "world"].reverse() Result: ["world", "hello"] |
.random() |
Get a random value from the list. Example: ["hello", "world"].random() Result: "hello" or "world" |
Function | Description |
---|---|
.keys |
All the keys in the object. Example: {name: "Miki", discrim: "6045"}.keys Result: ["name", "discrim"] |
.values |
All the values in the object. Example: {name: "Miki", discrim: "6045"}.values Result: ["Miki", "6045"] |
.has(key) |
True if the key exists in the object. Example: {name: "Miki", discrim: "6045"}.has("name") Result: true |
.del(key) |
Removes the key from the object. Example: {name: "Miki", discrim: "6045"}.del("name") Result: {discrim: "6045"} |
Function | Description |
---|---|
.from |
Start position of the range. Example: (1..10).from Result: 1 |
.to |
End position of the range. Example: (1..10).to Result: 10 |
.toArray() |
Create an list with every number in the range. Example: (1..10).toArray() Result: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] |
.random() |
Get a random number from the range. Example: (1..10).random() Result: A number between 1 and 10 |
.map(function) |
Create a new list and map every number in the range. Example: (1..10).map(i => i.upper()) Result: ["HELLO", "WORLD"] |
Function | Description |
---|---|
.name |
Get the function name. Example: (fun test() end).name Result: "test" |
Function | Description |
---|---|
.title(value) |
Sets the title of the embed. Example: embed().title("New title") |
.image(url) |
Sets the image of the embed. Example: embed().image("https://media.giphy.com/media/H9jrEhsr1pUMo/giphy.gif") |
.color(value) |
Sets the color of the embed. The value can either be a hex color (#FFFFFF ) or a HTML color (red ). Example: embed().color("red") |
.author(name, image, url) |
Sets the author of the embed. The image and url parameters are optional. Example: embed().author("Miki") |
.footer(content, url) |
Sets the footer content of the embed. The url parameter is optional. Example: embed().footer("Miki") |
.field(title, content) |
Adds a new field to the embed. Example: embed().field("Title", "Content") |
.inlineField(tile, content) |
Adds a new inline field to the embed. Example: embed().inlineField("Title", "Content") |
Function | Description |
---|---|
.keys |
All the keys in the storage. Example: storage.keys Result: ["name"] |
.set(key, value) |
Changes the value in the storage. Example: storage.set("name", "Miki") |
.get(key) |
Gets the value from the storage. Example: storage.get("name") Result: "Miki" |
.del(key) |
Remove the value from the storage. Example: storage.del("name") |
.clear() |
Clears the storage. Example: storage.clear() |