Beginners Guide to MS Teams Development #3 Messaging Action

Tomomi Imura 🐱 - Nov 3 '20 - - Dev Community

Hello, I hope you enjoyed the previous two tutorials on how to get started with Microsoft Teams development, (Developing Tabs on Teams and Bots

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. 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

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

📓 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!)
  • 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

👾 Technology to be used in this tutorial

Building an action

🎏 Grabbing the code sample

In this tutorial, I am using the 3rd party tool, Glitch 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!

First, let's just click this Glitch link to remix the project. 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

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.

🎛 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

🔖 Configuring a Messaging Extension

From the left menu, select Capabilities > Massaging Extensions. Go ahead and click the Setup button to set up.
App Studio
Give your app a name.
App Studio

🔐 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
(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
App Studio
App Studio

📦 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

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 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, but this is the recap of the initialization, and creating a bot adapter:

// 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();
Enter fullscreen mode Exit fullscreen mode

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:

app.post('/api/messages', (req, res) => {
  adapter.processActivity(req, res, async context => {
    await myBot.run(context);
  });
});
Enter fullscreen mode Exit fullscreen mode

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:

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 
  }
Enter fullscreen mode Exit fullscreen mode

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 on Teams documentation

📇 Displaying a modal dialog with Adaptive Cards

The dialog UI is created with Adaptive Cards, 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

To defining an Adaptive card and the content:

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
  }
}
Enter fullscreen mode Exit fullscreen mode

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.

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
        ]
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

In the code sample shown in the bots.js, I am using the simple UI "card" called Thumbnail Card 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

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 👋

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player