Integrate Meetup announcements with Microsoft Teams using Azure Logic Apps and Adaptive Cards
Tags: azure, serverless, meetup, microsoftteams
Published: 2020-12-22 01:03:05

---
title: Integrate Meetup announcements with Microsoft Teams using Azure Logic Apps and Adaptive Cards
published: true
tags: Azure,Serverless,Meetup,MicrosoftTeams
canonical_url: https://blog.siliconvalve.com/2019/05/24/integrate-meetup-announcements-with-microsoft-teams-using-azure-logic-apps-and-adaptive-cards/
---

I’ve recently found myself a member of so many meetups that it’s become increasingly difficult to track when a group announces a new event. Additionally, I have a few people in my close circle that I’d like to share new event announcements with.

As a result I wanted to find a way to track new events and ensure myself and others can see them, even if we aren’t direct members of the meetup group.

In this post I’ll look at how we can use Azure Logic Apps to publish new Meetup event information into Microsoft Teams, using Meetup’s REST API as the data source.

**Note:** from June 2020, Meetup requires OAuth2 authentication from clients wishing to call their API. I've written a [separate post](https://dev.to/simonwaight/adding-oauth2-support-to-your-meetup-api-custom-connector-for-azure-logic-apps-5a16) about how you can add OAuth2 support to the Custom Connector covered in this post.

### Understanding the Meetup REST API

Meetup publish their API spec at [https://www.meetup.com/meetup\_api/](https://www.meetup.com/meetup_api/) and for my purposes I’ve use the [V3 Events endpoint](https://www.meetup.com/meetup_api/docs/:urlname/events/#list) as my datasource.

I ran into a few challenges using the API which I’ve worked around in the resulting Logic App. These challenges are:

- Throttling: there is a relatively low number of allowed calls before your client is throttled. The exact numbers [aren’t documented](https://www.meetup.com/meetup_api/docs/#limits) though they are published back in the HTTP headers from the API (see below).

![Throttling Feedback in API](https://siliconvalve.files.wordpress.com/2019/05/2019-05-21_11-03-15.png?w=300&h=289 "Throttling Feedback in API")

Given Logic Apps’ ability to concurrently run Actions I was throttled the first time I ran! To work around this I used the [Delay Action](https://docs.microsoft.com/en-us/azure/connectors/connectors-native-delay) in the Logic App to slow down the rate at which I hit the API.

- Date Format differences: the Meetup API documentation says they accept / publish [ISO 8601 datetime](https://en.wikipedia.org/wiki/ISO_8601) values in their API. When trying to use the native ISO 8601 datetimes produced by Logic Apps I ran into problems because Logic Apps produces a UTC-based date/time. The API complained about this so I simply had to manipulate datetime values passed to the API to match the expected format. The time component of the call isn’t important, so I mostly just used the date component and manually added T00:00 for the time.
- Auth protection using OAuth2: The [HTTP connector](https://docs.microsoft.com/en-us/azure/connectors/connectors-native-http) for Logic Apps doesn’t currently support OAuth2 so I had to revert to using the API key method from Meetup. This method is no longer officially supported by Meetup, but works for my purpose right now. To ensure the API key is secured I keep it as a secret in Key Vault (note the value shows in clear text in the run history though, so make sure to [use security recommendations](https://docs.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app#secure-access-to-logic-app-run-history) when managing the Logic App if you use it).

### Creating our datasource

The easiest and cheapest way to hold the information about meetups we are going to track is to use [Azure Table Storage](https://docs.microsoft.com/en-us/azure/storage/tables/table-storage-overview), the original NoSQL storage option in Azure!

I landed on the following schema to hold the meetups I was tracking:

- PartitionKey: City – i.e. Sydney
- RowKey: Meetup’s URL Path – i.e. Azure-Sydney-User-Group
- LastEventId: string containing the Event ID from Meetup – i.e. 261477320
- LastEventTime: string containing ISO 8601 date/time of last Meetup – i.e. 2019-05-30T17:46 – more on this later
- TeamChannel: string containing name of Channel in Teams to post announcement to – i.e. Sydney
- Track: boolean denoting if we should follow this Meetup or not

In case my explanation isn’t clear here’s what a few rows look like in Explorer. The Timestamp field is automatically created for each row in Table Storage.

![Data Row in Explorer](https://siliconvalve.files.wordpress.com/2019/05/2019-05-24_08-44-52.png?w=1024&h=102 "Data Row in Explorer")

The LastEventTime field is used to hold a couple of values – if there have been no new meetups announced within the monitored window then this field holds the last time the Logic App ran.

I used this approach so we restrict the timeframe we check for meetups within to avoid picking up pre-scheduled meetups indefinitely.

The easiest way to import or create data in Table Storage is to use the free [Azure Storage Explorer](https://azure.microsoft.com/features/storage-explorer/) and then use a CSV as your data source.

### Using Adaptive Cards

When I wanted to post to Microsoft Teams I wanted a way to draw attention to the information and give Teams users a way to interact with it.

Initially I thought just posting into Teams using a standard message and including the Meetup event URL would suffice. It turns out this method doesn’t provide any user interaction at all – not even being able to click on the link!

Thanks to some folks on Twitter I was pointed at [Adaptive Cards](https://adaptivecards.io/) which is designed to provide a consistent way of presenting rich content in a card-like format across platforms.

I’m not a designer so I borrowed the [Activity Update sample](https://adaptivecards.io/samples/ActivityUpdate.html) and modified it for my use and included it in my Logic App, replacing some field information with content generated by the Logic App.

![Adaptive Card Sample](https://siliconvalve.files.wordpress.com/2019/05/2019-05-21_11-49-23.png?w=300&h=224 "Adaptive Card Sample")

> ❗ **Note:** you can’t embed HTML in Adapative Cards, so ensure whatever text you put into placeholders is only plain text.

Here’s what my Adaptive Card looks like (it’s the one embedded in the Logic App).

![My Adaptive Card](https://siliconvalve.files.wordpress.com/2019/05/2019-05-23_12-03-35.png?w=1100 "My Adaptive Card")

### Posting into Teams

In my scenario I wanted to post into a couple of Microsoft Teams. One of the Teams was only to a single Channel where I list all Meetups so I “hard coded” this Channel. For my second Team I wanted to dynamically choose the Channel based on the city the Meetup is in.

In the template I’ve provided on GitHub I only have the second experience so that you can see how you can find Teams Channel information in Logic Apps and then use the data later when you call back into Teams.

You will need to have access to the Team you are posting to – the initial connection authorisation uses your Office 365 user context.

> ❗ **Note:** If you need to find the unique ID of the Team you want to post to you can find it using Teams. Right-click on the Team and select “Get a link to the team”. In the URL you receive back you will find a parameter of ‘groupId’ – this value is the Team ID to use in your ARM template (see below!)

![Team ID](https://siliconvalve.files.wordpress.com/2019/05/2019-05-23_11-56-03.png?w=1100 "Team ID")

### Build your own!

I’ve created an Azure Resource Manager (ARM) template that contains all the components required to deploy this solution to your Azure environment. You’ll find it up on GitHub: [https://github.com/sjwaight/MeetupAndTeamsLogicApps](https://github.com/sjwaight/MeetupAndTeamsLogicApps)

Before you deploy the ARM template you’ll need to do a few things.

The following commands use the [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) and assume you have appropriate Subscription permissions to perform these actions (typically Contributor will be enough).

#### 1. Create a Resource Group

Change ‘location’ and ‘name’ to meet your needs (or you can leave them like this if you want).

```
az group create --location westus2 --name meetup-bridge-01
```

#### 2. Create an Azure AD Service Principal

This will be used for Key Vault access from the Logic App. You must have sufficient permissions in Azure AD to perform this action.

Change the ‘name’ and ‘scopes’ as required to match your environment.

```
az ad sp create-for-rbac \ 
--name meetupkeyvault \ 
--role reader \ 
--scopes /subscriptions/{YOUR\_SUBSCRIPTION}/resourceGroups/meetup-bridge-01
```

This will return a result that looks similar to the following

```
{ 
  "appId": "XXXX9fe0-XXX-XXXX-XXXX-e611592bXXXX", 
  "displayName": "meetupkeyvault", 
  "name": "http://meetupkeyvault", 
  "password": "XXXXXXXXXXXXXXXXX", 
  "tenant": "XXX08c33-XXXX-XXXX-XXXX-48065adeXXXX"
}
```

Make sure to note down the AppId, Password and Tenant fields.

#### 3. Deploy the ARM template

You will need to supply some parameters to deploy the ARM template.

- vaults\_meetupkeyvault\_name: the name of the Key Vault you wish to create or use.
- storageAccounts\_meetuplist\_name: the name of the Storage Account to create or use.
- ad\_service\_principal: Application ID of the Azure AD Service Principal to use to access Key Vault.
- deployment\_region: Azure Region to deploy the template to. This should match your Resource Group’s Region.
- target\_teams\_group\_id: the Unique ID of the Microsoft Teams group you want to use. I covered how to find this above.
- keyvault\_1\_token:clientSecret: the randomly generated password for your Azure AD Service Principal.
- meetup\_api\_key: your Meetup API key to be stored as a Secret in Key Vault.

After you’ve deployed the template you will find that the Logic App executed and failed. This is because you will need reauthorise the Teams and Key Vault Connectors. You can do this by opening the Connection in the Portal and following the process.

![Auth Connection](https://siliconvalve.files.wordpress.com/2019/05/2019-05-23_13-33-38.png?w=1100 "Auth Connection")

Before you do to the Key Vault Connector make sure your user has the ability to modify the target Key Vault. If you created the Key Vault (rather than using an existing one) using the ARM template then your user has no permissions on the Key Vault to begin with.

Once you’ve reauthorised the connections you should be good to go and will have frequent updates in Teams on when new Meetups are announced.

😎