Beginners Guide to MS Teams Development #3 Messaging Action
Tags: node, msteams, m365, javascript
Published: 2020-11-03 22:56:33

Hello, I hope you enjoyed the previous two tutorials on how to get started with Microsoft Teams development, (Developing [Tabs on Teams](https://dev.to/azure/beginners-guide-to-ms-teams-development-1-tabs-4e9k/?WT.mc_id=m365-9173-timura) and [Bots](https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m/?WT.mc_id=m365-9173-timura)

This is the third one of the beginner series, and this time, I will walk you through how to invoke an action from a message.

There are many different paths to learn how to build Teams apps, and this tutorial uses a bare-minimum code and minimal toolsets. Also, this tutorial is independent of the hosting environment, so I am not starting the process with the Azure setup, and basically, this should run on any environment, as long as you can run a browser. 

---

In this tutorial, I am introducing another Teams platform feature, [Messaging Extensions](https://docs.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/what-are-messaging-extensions/?WT.mc_id=m365-9173-timura). This feature comes with two different types, Action and Search, and it depends on how it interact with the UI elements and flows.

In this tutorial, I am showing how to built an **Action command**. 

# Teams features: Messaging Extensions - Action Command

Action commands allow you to present your users with a modal popup to collect or display information. When they submit the form, your web service can respond by inserting a message into the conversation directly, or by inserting a message into the compose message area and allowing the user to submit the message. 

![Teams action command](https://docs.microsoft.com/en-us/microsoftteams/platform/assets/images/task-module.png)

## Building a Morse Code message action

The app we are going to build invokes an action from a user message, extract the text, and convert it to a Morse code! 

How the app works is:

1. A user hovers a message to open the message menu, and choose the Morse Bot from the menu
2. When the user action is trigered, a payload is sent to your messaging endpoint (/api/messages)
3. This invokes the fetchTask - the message text data is extracted
4. A popup dialog is displayed. The user can edit the text content if they want, then submit
5. The app translate the text into a morde code, and display the content as a reply
6. The user can send the result to the client

This is how the result would look like:
![Teams app gif](https://dev-to-uploads.s3.amazonaws.com/i/kvwq8o7fix7qowgeuoml.gif)

### 📓 Prerequisites

To be able to install apps to Teams, your organization's admin needs to grant permission.

Otherwise, you can sign up for **Microsoft 365 developer program**, a free, renewable subscription that comes with a developer tenant sandbox and sample data pack, like mock user data!

- Permission to develop on Teams or developer tenant ([Sign up for M365 developer program!](https://developer.microsoft.com/en-us/microsoft-365/dev-program/?WT.mc_id=m365-devto-timura))
- App Studio - look for the app from the Apps menu in Teams client and install to your workspace
- Experience with Node.js and basic understanding of [Express.js](https://expressjs.com/)

### 👾 Technology to be used in this tutorial

- Node.js
- [Microsoft Bot Framework](https://dev.botframework.com/?WT.mc_id=m365-devto-timura)  
- [Adaptive Cards](https://adaptivecards.io/?WT.mc_id=m365-9173-timura) for building some UI snippets

## Building an action

### 🎏 Grabbing the code sample 

In this tutorial, I am using the 3rd party tool, [**Glitch**](https://glitch.com) to host and run this project and the rest of the tutorial series. *For a little more details what Glitch is and why I am using it, please refer my [previous tutorial](https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m)!*

First, let's just [click this Glitch link to *remix* the project](https://glitch.com/edit/#!/remix/msteams-msg-extension-action). Remixing is like the forking a repo on GitHub, so it generates a copy of the project for you, so you can modify the code in the way you want without messing with the original 🙌

[![Remix on Glitch](https://cdn.glitch.com/2703baf2-b643-4da7-ab91-7ee2a2d00b5b%2Fremix-button.svg)](https://glitch.com/edit/#!/remix/msteams-msg-extension-action)

Once you get your own project repo, it serves up the app automatically and you get your own web server URL. You will need the URL when you are setting up an app with App Studio later.

### ⚙️ App Configuration: Creating App Manifest with App Studio

The basic idea of App Package for Teams, please refer to the  [previous tutorial](https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m).

### 🎛 Using App Studio

Open **App Studio** app in Teams client. 

In App Studio, click the Manifest Editor tab from the top, then select **Create a new app** and fill out all the required fields including the Bot names, descriptions, etc.

Then, generate an App ID.
![Teams App Studio](https://dev-to-uploads.s3.amazonaws.com/i/hdhavjptelsoes0697nc.png)

### 🔖 Configuring a Messaging Extension

From the left menu, select Capabilities > **Massaging Extensions**. Go ahead and click the Setup button to set up.
![App Studio](https://dev-to-uploads.s3.amazonaws.com/i/ogfqgbe5wafpurrhlyt1.png)
Give your app a name.
![App Studio](https://dev-to-uploads.s3.amazonaws.com/i/mo63x8sqnrdz9wj7liqx.png)

### 🔐 App credentials

Copy the ID next to your bot name (something looks like `2cd53e8a-e698-4exx-...`) and paste it as an environment variable in your _.env_ file, which is supposed to be a hidden file (Rename the `.env-sample` to `.env`).

Under **App Passwords**, generate a new password, and copy it. Then paste it in your _.env_ file.

These credentials are used to initialize your bot adapter. (See index.js).

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/pnx9qfidui79ebzayjpb.png)
*(Step 3 in the screen image above will be explained at the next step.)*

### 🎬 Configuring an Action

At **Messaging Endpoint**, enter your web server URL, like, `https://[your project].glitch.me/api/messages` if you have remixed the sample repo.

Scroll to **Command** and click "Add".

In the dialog box -
1. Select "Allow users to trigger actions in external service..."
2. Select "Fetch a dynamic set of parameters from your bot"
3. Fill out the command ID and title text. Click "Massage" (Unselect other checkboxes if they are pre-selected). Leave the rest blank, then save.
	
![App Studio](https://dev-to-uploads.s3.amazonaws.com/i/x6zpdviv4xdq3bn90prz.png)
![App Studio](https://dev-to-uploads.s3.amazonaws.com/i/9obiddhhx1bbbhq93s0v.png)
![App Studio](https://dev-to-uploads.s3.amazonaws.com/i/oi5jelvbgswn1h1w0652.png)

### 📦 Installing the app manifest package

Go to **Finish > Test and distribute**.

If you get any errors, go fix it, otherwise, click **Install** your client.

![App Studio](https://dev-to-uploads.s3.amazonaws.com/i/cyokhzulqi44lpdkj6p4.png)

You can also download the zip file that contains `manifest.json`, and two icon images to install later or distribute.

As long as you remixed the code sample, the bot should work already. But let me quickly explain how it is coded before trying the bot.

## 🤖 Microsoft Bot Framework

The [Microsoft Bot Framework](https://dev.botframework.com/) is an open source SDK that allows you to build intelligent, enterprise-grade bots. 

This SDK is a powerful platform that not only for Teams, but also designed to work for wide types of chat bots, including web & mobile chat, Skype, Facebook, Amazon Alexa, Slack, Twilio, and more!

### 🔧 Initiating the bot service

First, there are two JS files in the Glitch code sample repo, **index.js** and **bots.js**. 

I am using Express to set up an HTTP server and routing HTTP requests. And the way to initiate the service is the same as [the previous Bots tutorial](https://dev.to/azure/beginners-guide-to-ms-teams-development-2-bots-590m), but this is the recap of the initialization, and creating a bot adapter:

```js
// Import bot services
const { BotFrameworkAdapter } = require('botbuilder');

// Bot's main dialog
const { ReverseBot } = require('./bot');

// App credentials from .env
const adapter = new BotFrameworkAdapter({
  appId: process.env.MicrosoftAppId,
  appPassword: process.env.MicrosoftAppPassword
});

// Create the main dialog
const myBot = new MorseBot();
```

*Note: In this example, I am using botbuilder version 4.10.0. If your code doesn't work as expected, check the version you are using!*

### 🦉 Forwarding requests to the bot logic

Use Express to handle the routing to listen for incoming requests: 

```js
app.post('/api/messages', (req, res) => {
  adapter.processActivity(req, res, async context => {
    await myBot.run(context);
  });
});
```
You have set up the URL in App Studio in the previous step. The `/api/messages` is your application’s endpoint URL to respond to client requests. 

### 🙋‍♀️ Handling the request 

Once a request is received at the endpoint and forwarded to the bot logic, your app receive the context of the request, then create a custom reply in **bots.js**.

See the `TeamsActivityHandler` is extended to create an appropriate handler for the request:

```js
class MorseBot extends TeamsActivityHandler {

  // Triggers when the message action is invoked by a user
  handleTeamsMessagingExtensionFetchTask(context, action) {
    /*
      We're going to create an adaptive card UI (modal dialog) here.
      In the dialog, the user confirms what text to be encoded to Morse code.
    */
  }
  
// Triggers when the dialog box is submitted from the FetchTask
  handleTeamsMessagingExtensionSubmitAction(context, action) {
    // display the result 
  }
```

The `TeamsActivityHandler` is a Teams specific class that handles messages- such as messages events and sending replies. 

In this scenario, when a user triggers an action from a message, `handleTeamsMessagingExtensionFetchTask` gets invoked, so your bot received the information about the message when the action was made from.

You can learn more about it at [Create and send the task module](https://docs.microsoft.com/en-us/microsoftteams/platform/messaging-extensions/how-to/action-commands/create-task-module?tabs=javascript/?WT.mc_id=m365-9173-timura) on Teams documentation

### 📇 Displaying a modal dialog with Adaptive Cards

The dialog UI is created with [**Adaptive Cards**](https://adaptivecards.io/?WT.mc_id=m365-9173-timura), which is a Microsoft open source to build snippets of UI in JSON, and can be used in Microsoft Teams, Outlook Actionable Messages, Cortana Skills, etc.

When `handleTeamsMessagingExtensionFetchTask` is invoked, get the message content text, and display it in a Adaptive card as a modal dialog, as the response.

![Adaptive Card in Team](https://dev-to-uploads.s3.amazonaws.com/i/3de82bu7wbr01t8n26gg.png)

To defining an Adaptive card and the content:
 
```js
const card = {
  type: 'AdaptiveCard',
  version: '1.0'
};

card.body = [
  { type: 'TextBlock', text: 'The message to be encoded to Morse code:', weight: 'bolder'},
  { id: 'editedMessage', type: 'Input.Text', value: content },
];
card.actions = [{
  data: { submitLocation: 'messagingExtensionFetchTask'},
  title: 'Encode to Morse!',
  type: 'Action.Submit'
}];

const adaptiveCard = CardFactory.adaptiveCard(card);

return {
  task: {
    type: 'continue',
    value: {
    card: adaptiveCard
  }
}
```

I am displaying the extracted message text in the `type: 'Input.Text'` so that the user can edit the text to be Morse-coded!

To view the full code, please see the **bot.js** file in the code sample in Glitch.

### 📮 Handling the user submission

Once a user submits the task module, `handleTeamsMessagingExtensionSubmitAction` gets triggered and your web service will receive an object with the command id and parameter values set.

In this sample code, it just checks if the custom data, `editedMessage` is there. And if so, grab the value (should be a string) and convert it and display the content to be composed as a new message.

```js
async handleTeamsMessagingExtensionSubmitAction(context, action) {

  if(action.data.editedMessage) {
    const text = action.data.editedMessage;
    const morseText = await encodeToMorse(text);

    return {
      composeExtension: {
      type: 'result',
        attachmentLayout: 'list',
        attachments: [
          // The message UI component here
          // Please refer to the sample code on Glitch to see the entire code
        ]
      }
    }
  }
}
```

In the code sample shown in the **bots.js**, I am using the simple UI "card" called [Thumbnail Card](https://docs.microsoft.com/en-us/microsoftteams/platform/task-modules-and-cards/cards/cards-reference#adaptive-card/?WT.mc_id=m365-9173-timura) that comes with Bot Framework to compose the result message, but you can use Adaptive Card too!

### 🤖💬 Trying your Message Action

Now, let's try the action! Go to the Teams client, and click one of the text messages (not in rich format or image).

If everything works as expected, you should be able to convert any text messages into a Morse code!

![Teams Message Action gif](https://dev-to-uploads.s3.amazonaws.com/i/kvwq8o7fix7qowgeuoml.gif)

I hope you get some good ideas about what you can do with Microsoft Teams platform with this tutorial, I hope you find better use cases than this and create something amazing! 

The next tutorial will walk you through how to build another type of Messaging Extension, which is a search command. See you next time 👋