---
description: >-
  Let's have a brief talk about shortcuts, bot actions, message actions or just
  menus. All of the words I just listed describe the same feature and let's
  officially call them shortcuts.
---

# Shortcuts

W**hat exactly are shortcuts in the tekos chat?**\
\
They appear in the chat menu as pre-programmed blocks for you to use. And don't worry, by programming we mean connecting nodes in the flow, as usual.

## **Where they can be found in the chat?**

We split them to two types: **Global shortcut** & **Message shortcut**.

![](https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fnodes%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPPOrj8wOkqqHV9Lrz%2F0.gif?generation=1611055871456625\&alt=media)

For the **Global shortcut**. You can find the menu next to the message input in the chat. It appears as a three bar hamburger. Don't worry if you can't find the menu right now, by default this element does not exist until you create your first shortcut or join the room with an already created one. Similar case is for the mobile, You can find the menu under the message input it also appears as a three bar hamburger.

![](https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fnodes%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPPOrk6DHToqOV6HMd%2F1.gif?generation=1611055871432642\&alt=media)

Contrary to global, the **Message shortcut** has some basic options like: Remove, Forward Message, Share Content, Quote. Maybe you already know where that menu is placed, if not you can find it after hovering on any message in the tekos chat. It's a three dots menu on the right side. And for the mobile you have to press and hold down the message to see the options.

## **But what can i do with the shortcuts?**

As always your imagination is the limit and also the four types of shortcuts action type.

**"Display Modal"** - (AdaptiveCard) Popup that displays the Adaptive Card.

**"External URL"** - (url) Link to external page, you can also display pages from flow by GET request.

**"Backend action"** - (post\_request) It is used to trigger an POST request. Most use cases will work with this action type. And also here we can find a big difference between global and message shortcuts payloads.

<div align="left"><img src="https://lh4.googleusercontent.com/Bb2-GlXyCVdpsINblmv_bHT1RsxnZj5hjzGm9ktb4HNioDx6UMjsRwTu9cE1t-EoUfwhJ6_QIthd5qa4m3mooQcT0ikH7Vj2UQIDfeF7B__WsasROmNeiFuc7zrlXrHL129PiTGN" alt="Global shortcut payload on trigger"></div>

<div align="left"><img src="https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fnodes%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPPOrmRI3l8ndUkUrs%2F3.png?generation=1611055871432186&#x26;alt=media" alt="Message shortcut payload on trigger"></div>

Using the eventId you can get the message content. See the reference:\
https://matrix.org/docs/spec/client\_server/latest#get-matrix-client-r0-rooms-roomid-event-eventid

**“Predefined message” -** (postback) Allows to send the predefined message to the chat set in the value field.

### **Let's start building!**&#x20;

As you already know we have 4 types of shortcut action and two places in which the shortcut can be placed

{% hint style="warning" %}
Remember that shorctcuts require HTTP PUT Method
{% endhint %}

## Create shortcut

<mark style="color:orange;">`PUT`</mark> `https://{{tekos_homeserver}}/_matrix/client/r0/rooms/{{room_id}}/state/{{shortcut_type}}`

This method allows to create shortcut assigned to the room

#### Path Parameters

| Name              | Type   | Description                                                                                                  |
| ----------------- | ------ | ------------------------------------------------------------------------------------------------------------ |
| shortcut\_type    | string | <p>The shortcut type:<br>bot.actions (Message shortcut)<br>bot.menu (Global shortcut)</p>                    |
| room\_id          | string | Room Id in which the bot is presented                                                                        |
| tekos\_homeserver | string | <p>Your home server address, the default one is m.tekos.co,<br>but we suggest to use env.get('BASE_URL')</p> |

#### Query Parameters

| Name          | Type   | Description                                                                                                          |
| ------------- | ------ | -------------------------------------------------------------------------------------------------------------------- |
| access\_token | string | <p>Thi is the access token of the bot presented in the room<br>We suggest using the flow.get('bot.default_room')</p> |

#### Request Body

| Name    | Type    | Description                                                                         |
| ------- | ------- | ----------------------------------------------------------------------------------- |
| menu    | array   | <p>Array of menu object assigned to the same bot,<br>check the bellow function.</p> |
| bot\_id | string  | Bot Id presented in the room                                                        |
| active  | boolean | Turn on and of the shortcut, values: true / false                                   |
| icon    | string  | Url to icon displayed in the global shortcut                                        |

{% tabs %}
{% tab title="200 Responses with event_id of the state" %}
```javascript
"event_id": "$qHn5-uVS0oGTh51ilcxgLb-nT9RPwLuF4piuqAPhlsI"
```
{% endtab %}

{% tab title="401 " %}
```javascript
msg.payload = {
    "errcode":"M_UNKNOWN_TOKEN",
    "error":"Invalid macaroon passed.",
    "soft_logout":false
}
```
{% endtab %}

{% tab title="403 Entering the wrong Room Id" %}
```javascript
msg.payload = {
    "errcode":"M_FORBIDDEN",
    "error":"Unknown room"
}
```
{% endtab %}

{% tab title="404 If you enter the wrong url" %}
```javascript
<html>  
    <head>
        <title>404 - No Such Resource</title>
    </head>  
    <body>    
        <h1>No Such Resource</h1>    
        <p>No such child resource.</p>  
    </body>
</html>
```
{% endtab %}
{% endtabs %}

{% code title="Example code in the function node" %}
```javascript
let shortcut_type = //you cen enter bot.actions (Message shortcut) or bot.menu (Global shortcut) depending where you want fo the shortcut to be displayed

msg.url = "https://"+env.get('BASE_URL')+`/_matrix/client/r0/rooms/`+flow.get('bot.default_room')+`/state/`+shortcut_type+`?access_token=`+flow.get('bot.bot_access_token')
//By the default we use the bot as the menager of the menu action

msg.payload = {
     "bot_id": "@spopin-dev1:m.tekos.co", //Bot assigned to the menu
     "active":true, //Turn on and of shortcut
     "icon": "https://image.flaticon.com/icons/svg/2560/2560810.svg", //url to icon
     "menu": [
       {
         "body": "Trigger endpoint", //Name displayed in the menu
         "type": "post_request", //all actions can be found above
         "value": env.get("FLOW_URL")+"/test_shortcut/v1" //Depends on the action type
       },
     ]
   }
return msg;
```
{% endcode %}

**Body** - It's the name displayed in the menu\
**Type** - all actions types can be found above\
**Value** - Depends on the action type. For postback just enter a text that will be send to the chat,\
for url enter the url to page that you want to be opened on click. \
For AdaptiveCard & post\_request should contain link to the endpoint

{% hint style="info" %}
env.get("FLOW\_URL") - This enviorment contains link to your flow instance (e.g. https://instance-name.tekos.co)
{% endhint %}

### Multiply shortcuts for one bot

The subflow we previously showcased allows the user to create only one shortcut for the bot, but it’s possible to have more than one shortcut for each bot.

![Bot with multiple shorcut actions](https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LSqSDdProPIpKBElfLq%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPbn7sa1T0Fqke2iy4%2Fimage.png?alt=media\&token=1c938e5c-7f84-4ad8-840e-22ca4ba13f1f)

Let’s take a look at the code with multiple shortcuts

```javascript
//msg.url & msg.headers remains the same

msg.payload = {
     "bot_id": "@spopin-dev1:m.tekos.co", //Bot assigned to the menu
     "active":true, //To be implemented in the future
     "icon": "https://image.flaticon.com/icons/svg/2560/2560810.svg", //url to icon
     "menu": [
       {
         "body": "Spopin Postback",
         "type": "postback",
         "value": "menu"
       },
       {
         "body": "Spopin Request POST",
         "type": "post_request",
         "value": env.get("FLOW_URL")+"/test_shortcut/v1"
       },
       {
         "body": "See Samsung S21 Ultra",
         "type": "url",
         "value": "https://www.youtube.com/watch?v=lvV3jSLYK8A"
       }
     ]
   }

```

We have an menu array which contains multiple shortcuts that will be available with our bot.

## Subflow - Create 1 shortcut&#x20;

<div align="left"><img src="https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-LSqSDdProPIpKBElfLq%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPefnXz35t6qiuu7Rt%2Fimage.png?alt=media&#x26;token=3023b9bb-9968-4868-99ee-06cc8c3b0015" alt="Prebuilt subflow by Tekos"></div>

This subflow was built to easily create shortcut connected with the bot created in the same flow tab.

Example use cases:

<div align="center"><img src="https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fnodes%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPPOrnSEOFMJrQrJL5%2F4.png?generation=1611055871437036&#x26;alt=media" alt="You can find here a bunch of usage examples."></div>

Let's take a look whats is inside the red subflow named "Create 1 shortcut"&#x20;

1. Name that will be displayed in the flow editor
2. Input Name to be displayed in the Menu.
3. Select a type **Global** | **Message**
4. Choose select response type: **Display Modal** | **External URL** | **Backend Action** | **Predefined message**
5. For the **Response URL / Value** stuff gets a little bit more complicated, but don't worry. Links may vary on the response type. For the External Url just paste the link to the page, but for the Display Modal and Backend Action enter the link to the post action. Let's take an example on the image above about "Send a simple message to the current room". The response url should contain an endpoint for **/message.** By default the link contains your tekos instance name as a prefix before [.tekos.co](https://.tekos.co/) and the trigger for the post webhook.
6. URl of the image field is to set the custom image displayed in the global shortcut menu.

![](https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fnodes%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPPOrohegw-eSfcARv%2F5.png?generation=1611055871420713\&alt=media)

###

We suggest using the “**Create 1 Shortcut**” with create bot flow

![](https://2146957470-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2Fnodes%2F-MRPJJYjr0DA-tAhUI-3%2F-MRPPOrqOJBW4vvMS5VH%2F7.png?generation=1611055871416001\&alt=media)

Code for the "Create 1 Shortcut" subflow:

{% code title=" "Create 1 Shortcut" JSON" %}
```javascript
[{"id":"4d023e03.75cd8","type":"subflow","name":"Create 1 Shortcut","info":"**Name** - Give the name of tab in the action menu (shortcut)\n\nType -","category":"","in":[{"x":320,"y":80,"wires":[{"id":"1d7c48b9.b05497"}]}],"out":[],"env":[{"name":"shortcut_name","type":"str","value":"","ui":{"icon":"font-awesome/fa-bars","label":{"en-US":"Name"},"type":"input","opts":{"types":["str"]}}},{"name":"shortcut_type","type":"str","value":"","ui":{"icon":"font-awesome/fa-arrows","label":{"en-US":"Type"},"type":"select","opts":{"opts":[{"l":{"en-US":"Message"},"v":"message"},{"l":{"en-US":"Global"},"v":"global"}]}}},{"name":"response_type","type":"str","value":"","ui":{"icon":"font-awesome/fa-arrow-circle-o-right","label":{"en-US":"Response Type"},"type":"select","opts":{"opts":[{"l":{"en-US":"Display Modal"},"v":"display_modal"},{"l":{"en-US":"Backend Action"},"v":"backend_action"},{"l":{"en-US":"External URL"},"v":"external_url"},{"l":{"en-US":"Predefined message"},"v":"postback"}]}}},{"name":"response_url","type":"str","value":"/**","ui":{"icon":"font-awesome/fa-send-o","label":{"en-US":"Response URL / Value"}}},{"name":"image_url","type":"str","value":"","ui":{"icon":"font-awesome/fa-image","label":{"en-US":"Url of image"}}}],"color":"#E9967A","icon":"node-red/status.svg"},{"id":"e6fbf29e.af1f9","type":"http request","z":"4d023e03.75cd8","name":"","method":"PUT","ret":"obj","paytoqs":"ignore","url":"","tls":"","persist":false,"proxy":"","authType":"","x":695,"y":80,"wires":[["c13a3a05.631208"]],"l":false},{"id":"9fceb53b.6fd748","type":"function","z":"4d023e03.75cd8","name":"Menu Action","func":"msg.url = \"https://\"+env.get('BASE_URL')+`/_matrix/client/r0/rooms/`+flow.get('$parent.bot.default_room')+`/state/${msg.action}?access_token=`+flow.get('$parent.bot.bot_access_token')\n\nlet value\n\nif(msg.type == \"url\" || msg.type == \"postback\"){\n value = env.get('response_url')\n}else{\n value = env.get(\"FLOW_URL\")+env.get('response_url')\n}\n\nmsg.payload = {\n \"bot_id\": flow.get('$parent.bot.bot_id'), // optional\n \"icon\": env.get(\"image_url\"),\n \"menu\": [\n {\n \"body\": env.get('shortcut_name'),\n \"type\": msg.type,\n \"value\": value\n }\n ]\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":550,"y":80,"wires":[["e6fbf29e.af1f9","ded4354f.e3c868"]]},{"id":"ded4354f.e3c868","type":"debug","z":"4d023e03.75cd8","name":"global shortcut resp","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":750,"y":20,"wires":[]},{"id":"1d7c48b9.b05497","type":"function","z":"4d023e03.75cd8","name":"","func":"if(env.get('response_type') == \"display_modal\") msg.type = \"AdaptiveCard\"\nif(env.get('response_type') == \"backend_action\") msg.type = \"post_request\"\nif(env.get('response_type') == \"external_url\") msg.type = \"url\"\nif(env.get('response_type') == \"postback\") msg.type = \"postback\"\n\nif(env.get('shortcut_type') == \"message\") msg.action = \"bot.actions\"\nif(env.get('shortcut_type') == \"global\") msg.action = \"bot.menu\"\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":435,"y":80,"wires":[["9fceb53b.6fd748"]],"icon":"node-red/switch.svg","l":false},{"id":"c13a3a05.631208","type":"debug","z":"4d023e03.75cd8","name":"global shortcut out","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":830,"y":80,"wires":[]},{"id":"d155c356.58b6f","type":"subflow:4d023e03.75cd8","z":"58869ccd.32a424","name":"","env":[{"name":"shortcut_name","value":"Create Calendly Link 📅","type":"str"},{"name":"shortcut_type","value":"global","type":"str"},{"name":"response_type","value":"backend_action","type":"str"},{"name":"response_url","value":"/calendly/events","type":"str"},{"name":"image_url","value":"https://i.imgur.com/kMHM4DR.png","type":"str"}],"x":590,"y":200,"wires":[]}]
```
{% endcode %}

## Sharing shortcuts with team members

Information about each shortcut is stored in the room state event, so to get them working the bot needs to be together with you in the same room and you don’t need the admin privileges in the room to get it working. That means you can invite your team members to the room and they will have access to the same actions as you, but keep in mind that for apps that require api keys or oauth access all users in the room with the bot will have access to your data.

## Removing shortcut from menu

All you need to do is just quit the room with the bot responsible for specified shortcut
