Creating a Mastodon Bot With AWS Lambda

Creating a Mastodon Bot With AWS Lambda
Photo by Battenhall / Unsplash

This post might seem like déjà vu for anyone who has read my blog post on building a Twitter bot with AWS Lambda, and it certainly felt that way when building my Mastodon bot. There was very little code that I had to change in order to make my bot work on Mastodon beyond using a new package and API secret.

There's a Python wrapper for the Mastodon API that I utilized for this project, which you can find here.

For anyone interested in building a Mastodon bot, make sure that the instance you are building your bot on is fine with automated accounts. There's a Mastodon instance located at botsin.space that has been setup specifically for this use case that I registered with. Once registered, navigate to your account Preferences > Development and create a new application.

Go ahead and enter a name for your application and feel free to leave the rest of the default values for now.

Once your application is created, you should have a client key, a client secret, and an access token available. Save your access token somewhere convenient as this is what we will be using.

As a matter of fact, a great place to keep this access token is in AWS Systems Manager Parameter Store. I've stored my access token here as a secure string that gets called and decrypted by my AWS Lambda function on runtime.

I'm not going to go over the details of the screenshots I've taken for my King of the Hill project or how I organized the S3 bucket as you can find all of that information in my original post, but I've shared my updated code in full below:

import mastodon
from mastodon import Mastodon
import boto3
import os
import random


def send_toot(event, context):
    BASE_URL = "https://botsin.space"
    BUCKET_NAME = "koth-frames"
    keyArray = []
    ssm = boto3.client("ssm")
    
    # You can use the get_parameter (singular) method here, 
    # I am using multiple params in my other project and was 
    # just re-using code to save time.
    auth_keys = ssm.get_parameters(
    	Names=["koth_mastodon"], WithDecryption=True)
    access_token = auth_keys["Parameters"][0]["Value"]

    m = Mastodon(access_token=access_token, api_base_url=BASE_URL)

    s3 = boto3.resource("s3")
    s3bucket = s3.Bucket(BUCKET_NAME)
    randomSeason = random.randint(1, 13)

    episodeDict = {
        1: 12,
        2: 23,
        3: 25,
        4: 24,
        5: 20,
        6: 21,
        7: 23,
        8: 22,
        9: 15,
        10: 15,
        11: 12,
        12: 22,
        13: 24,
    }

    randomEpisode = random.randint(1, episodeDict[randomSeason])
    randomSeason = str(randomSeason)
    randomEpisode = str(randomEpisode)

    print("Season " + randomSeason + ", Episode " + randomEpisode)

    for obj in s3bucket.objects.filter(Prefix=randomSeason + "/" + randomEpisode):
        # add all frame key values from episode to an array
        keyArray.append("{0}".format(obj.key))

    numFrames = len(keyArray)
    randomFrame = random.randint(0, numFrames)
    KEY = keyArray[randomFrame]
    print("frame from second # " + str(randomFrame))
    s3.Bucket(BUCKET_NAME).download_file(KEY, "/tmp/local.jpg")
	
    # We have to first create a media ID when uploading an image
    media = m.media_post("/tmp/local.jpg")
    # Then we can reference this media ID in our status post
    m.status_post(
        status=f"Season {randomSeason}, Episode {randomEpisode}", media_ids=media
    )

    os.remove("/tmp/local.jpg")
    return None

Just as before, the Mastodon.py package was installed locally and zipped up along with the code and uploaded to Lambda where I've defined the handler as koth_mastodon.send_toot. Very simple and took me less than an hour from start to finish! If you manage to setup your own bot, let me know on Mastodon! Happy tooting!

Mastodon