DEV Community

Cover image for A Golang bot to count down the best day of your life - the holidays
Luis Gustavo Macedo
Luis Gustavo Macedo

Posted on

A Golang bot to count down the best day of your life - the holidays

Returning with my desire to share knowledge and experience, today i will show a very cool project that i built in the last year.

At the time, I was in the middle of my degree. Although I liked the university and thought that academia is very important for the education of a great software developer (but not mandatory), the holidays are a time that every university student looks anxiously.

The Idea 💡

Then, at the time as I already my studies in Go, and I have a idea, why not make a bot for twitter?🤔 To learn more about golang and make a cool project.

A bot that makes a tweet every day telling how many days are left until college holiday, for me and people at my university accompany.

Repository of project -> https://github.com/Luisgustavom1/go-twitter-bot

Today that's what I want to show, I'll show the simple code of bot and how I built the infra in AWS to automate this process, obviously using the free tier🤑.

Before start I have divided it into 4 main steps 📑:

  • Create a main function that must receive a date and return how many days are left until this date.
  • Connect with twitter to make a tweet.
  • Configure the function in AWS Lambda.
  • Give a way of execute lambda function every day.

1. The function

The code of this feature is very simple.

I have a function to format date and another to subtract the date.

package main

import (
    "log"
    "math"
    "time"
)

type DaysRemaining int

func main() {
    VACATION_DATE := "2023/06/29 23:00:00 -03"

    vacationDateFormatted, err := getVacationDateFormatted(VACATION_DATE)
    if err != nil {
        log.Fatal(err)
    }
    daysToVacation := getDaysRemaining(vacationDateFormatted)

    log.Println("tweet", daysToVacation)
}

func getVacationDateFormatted(date string) (time.Time, error) {
    const shortFormat = "2006/01/02 15:04:05 -07"
    // Format date to this format and timezone 👆👆 
    dateParsed, err := time.Parse(shortFormat, date)

    if err != nil {
        return dateParsed, err
    }

    return dateParsed, nil
}

func getDaysRemaining(date time.Time) DaysRemaining {
    today := time.Now()
    duration := date.Sub(today)
    // Subtract today from vacation date 
    return DaysRemaining(math.Ceil(duration.Hours() / 24))
}
Enter fullscreen mode Exit fullscreen mode

The main logic is basically that, in another post we can explore more about golang and its powers, but today i just want to give an overview of the code.

2. Connect with twitter

At the time I used this client library to abstract the twitter API, but unfortunately it is deprecated😭

So today maybe it is not the best option. You can venture into twitter api.

In this step I had to generate api keys and access tokens. Every time I get to this part to integrate with third party, I get lost where get this secrets, so here are the ones from twitter api key and access token.

package main

import (
    "log"
    "math"
    "time"
    "os"

    "github.com/dghubble/go-twitter/twitter"
    "github.com/dghubble/oauth1"
)

func main() {
    //...
    // Initial config to oauth 1.0a
    config := oauth1.NewConfig(
        os.Getenv("API_KEY"),
        os.Getenv("API_KEY_SECRET"),
    )
    token := oauth1.NewToken(
        os.Getenv("ACCESS_TOKEN"),
        os.Getenv("ACCESS_TOKEN_SECRET"),
    )

    // Create a http client with oauth 1.0a method
    httpClient := config.Client(oauth1.NoContext, token)

    // Create the client to access twitter api methods(endpoints)
    client := twitter.NewClient(httpClient)

    //...

    daysToVacation := getDaysRemaining(vacationDateFormatted)
    messageToTweet, err := generateMessageToTweet(daysToVacation)
    if err != nil {
        log.Fatal(err)
    }

    // Method to publish a tweet
    client.Statuses.Update(messageToTweet, nil)
}
Enter fullscreen mode Exit fullscreen mode

3. Create the Lambda Function

At the time I only knew the concept about lambda functions so it would be one more tech that I would learn with this simple project.

Let's create lambda function.

  1. Choose Author from scratch.
  2. Put the name of your bot.
  3. Select the language and architecture.

AWS dashboard to create a lambda function

Now, to work with Lambda using go, we have to change the code a little bit and use this official aws tool.

So we import the package, rename main function to Handler and create a new main that will execute the .Start() method, of aws tool.

The Handler function is method that manipulate the events. The main function is required, is the entry point where aws lambda will run our code.

package main

import (
    // ...
    // Import the package
    "github.com/aws/aws-lambda-go/lambda"
)

type DaysRemaining int

func main() {
    // The `main` should start the Handler function
    lambda.Start(Handler)
}

// Out function that contains the logic
func Handler() {
    VACATION_DATE := "2023/06/29 23:00:00 -03"

    config := oauth1.NewConfig(
        os.Getenv("API_KEY"),
        os.Getenv("API_KEY_SECRET"),
    )
    // ...
}
Enter fullscreen mode Exit fullscreen mode

If you want developing something more complexity, with multiply events and features, you can access the event name and work with context in Handler function, see more.

After finishing the code, don't forget of upload the code to AWS lambda, either by uploading the .zip file or by configuring an s3 bucket, and add the twitter keys in the environment variables (Configuration > Environment variables).

4. Running every day

Someone once told me that

"Developers are the laziest, because they want to automate everything"

Sice obviously I won't execute manually the lambda every day, we can use the AWS CloudWatch Events to trigger the function at the specific time.

Then let's add a trigger

AWS lambda dashboard to add a trigger

  • Select EventBridge (CloudWatch Events).
  • Check Create a new rule.
  • Check Schedule Expression.
  • Put the cron expressions.

For my bot I use this cron cron(00 09 ? * * *), It will run every day at 09:00 UTC, that is, 06:00 in GTM-3.
Process to create the trigger

If when creating your lambda function, you kept these configs checked (the default configs): Permissions > Change default execution role > Create a new role with basic Lambda permissions. You won't have to worry with the IAM role for lambda access the cloud watch, the AWS already create the role for you, lambda permissions.

That's it, see the bot perfil in twitter.

Hope you are enjoying.

Follow me on social networks:

Top comments (0)