DEV Community

Taha Yağız Güler
Taha Yağız Güler

Posted on

Mastadon Bot with AWS Lambda, S3, CloudWatch, and SSM

In this post I show you how I set up the MastadonBot to share random frames from the movie Taxi Driver.
This bot was created by taking inspiration from Cameron Ezell.

I also created this bot using Terraform. You can browse Github MastadonBot_AWS.

How I got the frames?

Python script "ExtractImagesFromVideoFile" I wrote for capturing screenshots at specified intervals from a video file using ffmpeg. This Python script captures screenshots from a video file at specified intervals (e.g., 1 second) using ffmpeg.

Uploading frames!

First of all, I created an S3 bucket and uploaded the screenshots I wanted to share to this bucket and used the following path while uploading the screenshots.

After saving about 7000 screenshots it would take quite a while to upload them to the S3 bucket so I created an EC2 instance and uploaded the files via FTP then copied the S3 bucket via the aws cli > aws s3 cp ./ s3://your-bucket/ --recursive.

Create your Application

For anyone interested in building a Mastodon bot, make sure the instance you create your bot on is fine with automated accounts.

After signing up, create an app from Preferences > Development.

(botsin.space)

App
Enter a name for your application and default values for now.
Keys

I keep the access token as SecureString type using the AWS Systems Manager Parameter Store. This is an important step for security.

Lambda Function

Boto3(AWS Lambda) script for randomly selects screenshots stored in S3 and enables sharing.

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

def lambda_handler(event, context):
    BASE_URL = "https://botsin.space"
    BUCKET_NAME = "movieframebucket" # XXXXXXX
    keyArray = []
    ssm = boto3.client("ssm")

    auth_keys = ssm.get_parameters(
        Names=["my_consumer_key"], WithDecryption=True) # XXXXXXX
    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)

    try:
        for obj in s3bucket.objects.filter(Prefix="taxi_driver_frames/"): # XXXXXXX
            # add all frame key values from episode to an array
            keyArray.append("{0}".format(obj.key))
    except Exception as e:
        # If there is an error, raise the exception and stop the function
        raise e

    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")

    random_objectNumber = re.search(r'\d+', KEY).group()
    time_in_seconds = int(random_objectNumber)
    minutes, seconds = divmod(time_in_seconds, 60)
    hours, minutes = divmod(minutes, 60)
    time_format = "{:02d}:{:02d}:{:02d}".format(hours, minutes, seconds)
    frameInfo = "Taxi Driver | {:02d}:{:02d}:{:02d}".format(hours, minutes, seconds) 

    # 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=frameInfo, media_ids=media)


    os.remove("/tmp/local.jpg")
    return None
Enter fullscreen mode Exit fullscreen mode

I installed the Mastadon package locally and zipped it with this code I wrote then uploaded it to Lambda.

CloudWatch Event for Lambda

I created a CloudWatch Event for Lambda to publish a post every 30 minutes.
ImAnd here is our Mastadon bot ready!

I may have missed a few parts, don't hesitate to reach out to me if you need help. I would like to help you as much as I can!

Top comments (0)