- Simon Waight
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.
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.
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).
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: holds a list of processed Meetup Member IDs so we don't process a Member more than once
- Azure 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 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
- Azure Logic Apps Gmail Connector: one of the existing Logic Apps Connectors.
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:
As part of this solution the maintenance of this list is a manual one. You can use Azure 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 and text content 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 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.
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.
Meetup API Custom Connector
As of February 1, 2022, the Meetup REST API has been retired and no longer functions. I am leaving this post up for learning purposes, but the API Custom Connector no longer works. I will update to the new GraphQL API in due course and will blog about it when ready.
I developed a re-usable Meetup Connector 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 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.
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.
Deploying it all
I have an Azure Resource Manager (ARM) template defined for this overall solution which you can find on GitHub.
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.