Using Azure services to deal with spam bots on Meetup
Tags: azure, cognitiveservices, logicapps, resourcemanager
Published: 2019-10-11 01:18:52

---
title: Using Azure services to deal with spam bots on Meetup
published: true
date: 2019-10-08 23:38:25 UTC
tags: Azure,Cognitive Services,Logic Apps,Resource Manager
canonical_url: https://blog.siliconvalve.com/2019/10/09/using-azure-services-to-deal-with-spam-bots-on-meetup/
---

If you’ve been a meetup user or admin for the last couple of years then no doubt bots posting dodgy content on your Group's discussion boards (and the resulting notifications) have become the bane of your life.

These bots join meetups and then start posting comments in either the group or individual events which are then bounced to members of the Group via email or notifications.

There are a few tell-tale signs of these bots:

- their profile picture is usually a ‘glamour’ shot of a woman
- typically they only have a one name in their profile
- often their “location” is not in the same city as your meetup
- sometimes their bio contains a link to an adult content site.

Here’s a sample of the ‘new Members’ view containing three bots.

![Meetup Bots](https://siliconvalve.files.wordpress.com/2019/09/meetup-bots-02.png?w=253&h=300 "Meetup Bots")

Once they join they either post to the all-members discussion thread (you’ll hopefully have disabled this feature), and increasingly they RSVP to an event and then post into the discussion thread there (this can’t be disabled right now). Sample message below.

![Meetup Bot Message](https://siliconvalve.files.wordpress.com/2019/09/meetup-bots-04.png?w=300&h=109 "Meetup Bot Message")

For some reason, despite this being an ongoing issue, there hasn’t been any announced intent from Meetup to deal with these spam bots for Groups configured as ‘open’. As a result I thought I’d look at a way to identify and flag problematic accounts for admins without them needing to do anything other than have an email inbox (and an Azure subscription).

### A solution

In this post I’m going to show how we can use some serverless logic in Azure to check new members and flag them as requiring attention.

> Note: I could also auto-mark these members as blocked using the Meetup Pro API, but the goal here is to show you how you can use these features quickly and easily if you’re just a standard tier paid Meetup admin. Also, you probably don’t want to block valid new members if they are flagged as suspect based on the criteria we are using.

These are building blocks I’m going to use:

- [Azure Table Storage](https://azure.microsoft.com/en-us/services/storage/tables/): holds a list of processed Meetup Member IDs so we don’t process a Member more than once
- Azure Cognitive Services [Content Moderator](https://azure.microsoft.com/en-us/services/cognitive-services/content-moderator/): we’ll use this service to process the Member’s profile images and text to detect inappropriate content
- Azure Logic Apps: a [serverless, no-code](https://docs.microsoft.com/en-us/azure/logic-apps/) way of developing solutions in Azure
- Azure Logic App Meetup API Custom Connector: I’ve built this to make working with the Meetup API easier in Logic Apps. Find it [on GitHub](https://github.com/sjwaight/LogicAppsMeetupReadOnlyPublicConnector)
- Azure Logic Apps Gmail Connector: one of the [existing Logic Apps Connectors](https://docs.microsoft.com/en-us/connectors/gmail/).

#### Table Storage

So you can use this solution for multiple Meetups I’ve built a very basic Table structure that we can use to track already processed Meetup Members.

This list can be pruned fairly often as we are only looking at a small number of recently joined accounts which will change over time.

The table structure is using just the default three columns available:

- PartitionKey: Meetup URL Name (i.e. Azure-Sydney-User-Group)
- RowKey: Meetup Member Unique ID (i.e. 98827992)
- Timestamp: the ISO8601 date/time the record was written to Table Storage

Here’s a sample of my live table:

![Parsed Members Table](https://siliconvalve.files.wordpress.com/2019/10/2019-10-07_20-57-51.png?w=1024&h=269 "Parsed Members Table")

As part of this solution the maintenance of this list is a manual one. You can use [Azure Storage Explorer](https://azure.microsoft.com/en-us/features/storage-explorer/) or the Azure Portal to maintain this table (or write a Function or Logic App to delete old records periodically based on their age).

#### Azure Cognitive Services Content Moderation

In this solution I’m using the [image](https://docs.microsoft.com/en-us/azure/cognitive-services/Content-Moderator/image-moderation-api) and [text content](https://docs.microsoft.com/en-us/azure/cognitive-services/Content-Moderator/text-moderation-api) moderation APIs to parse profile information and flag potentially risky content. I’m using the free tier which limits me to one call per second so I put a delay into my Logic App and set the parallelism to 1.

You could, if you wished, build a larger solution that makes use of the [Human Review Tool](https://contentmoderator.cognitive.microsoft.com/dashboard) that is bundled with Content Moderator and hook the results of the Tool back into the Meetup API to block a user (this would require a Meetup Pro license though).

Here’s a sample of an image being parsed in the Logic App.

![Content Moderator Action](https://siliconvalve.files.wordpress.com/2019/10/profile-pic-moderator-check.png?w=910&h=1024 "Content Moderator Action")

#### Azure Logic App

I’ve become quite attached to building solutions using Logic Apps. They are a great way to quickly create powerful integration solutions and the Connectors make this much easier than it otherwise would be with a code-first solution.

The trigger I’m using is only running once every 6 hours – you could, if you wanted, run this more often, particularly if you have a popular group that has lots of joining members. I am also only pulling back 20 Member records at a time, so if you’re likely to grow faster than that between requests then you should increase that also.

![Recurrence Timing](https://siliconvalve.files.wordpress.com/2019/10/2019-10-07_22-01-26.png?w=1100 "Recurrence Timing")

#### Meetup API Custom Connector

I developed a [re-usable Meetup Connector](https://github.com/sjwaight/LogicAppsMeetupReadOnlyPublicConnector) you can use to easily interface with their public read-only API. It’s used in this solution.

If you are considering sitting the [AZ-203 Certification Exam](https://www.microsoft.com/en-us/learning/exam-az-203.aspx) then you’ll need to work with Logic Apps and learn about Custom Connectors, which is what I’ve built to interface with Meetup in this instance. A sample Action is shown below.

![API record limit](https://siliconvalve.files.wordpress.com/2019/10/2019-10-07_22-01-51.png?w=1100 "API record limit")

#### Send notifications via Gmail

In order to keep things simple I am using the existing Logic Apps Gmail Connector which requires only an OAuth grant to authorise a connection to send email on a user’s behalf.

Once you have this setup the resulting email looks similar to the below. This allows a Group admin to quickly click through to suspicious Member accounts and make a call on the spot if this a real member or not.

![Email for potential accounts](https://siliconvalve.files.wordpress.com/2019/10/2019-10-04_22-55-50.png?w=1100 "Email for potential accounts")

#### Deploying it all

I have an Azure Resource Manager (ARM) template defined for this overall solution which you can [find on GitHub](https://github.com/sjwaight/AzureLogicAppsMeetupSpamBotFilter).

If you have permissions in an Azure Subscription you can click the “Deploy to Azure” button and then fill in some blanks in order to deploy the solution.

Once deployed the Logic App will run once which is fine, though it won’t work as expected. In order get the Logic App working fully you’ll need to:

- Manually create a new Table in the Storage Account the ARM template creates
- Authorise the Gmail connector against an email account you want to use
- Configure the Connections for Table Storage and Cognitive Services.

So there we go, a code-free way to utilise Azure’s “AI on an API” and some business logic to help reduce the chances of your Group being spammed by bots.

😎

PS – you can block people joining your Meetup group without an approval using the in-built settings in Meetup. I’m not a fan as it introduces friction for valid new Members to join, but it does stop the spambots being able to abuse your Meetup Group.