Twitter BOT to send joke and image (lambda + typescript)
metacollective
Posted on February 15, 2022
In this blog post, I am going to show you how you can build your own twitter bot which will periodically send out tweet (joke) with images
How will it work?
- We will get a random joke from https://jokeapi.dev/ API. It's free with some limitation on hit rate etc.
- We will get a random but relevant GIPHY image using https://developers.giphy.com/ API
- We will create and send a tweet using twitter api and
twitter-api-client
node package
End Result will look like this
Prerequisite
- You should have a twitter account to register with twitter's developer portal
- AWS access key & secret key to deploy on AWS
Step 1: Register with twitter's developer portal and get relevant keys
Getting keys from twitter's developer account is pretty easy and straight forward process. You can get a step by step guide from this video -
Step 2: Register with giphy's developer account and get their access key
Again, this is very easy and self explanatory (https://developers.giphy.com/), but in case you need some detailed information on this API and how to get its access keys, you can watch this video -
Step 3: Now you have your twitter & giphy keys, so let's get started with writing the bot code
We will be using the serverless framework to write this lambda function.
Install serverless globally
npm install -g serverless
Create an typescript project from the serverless template library
sls create --template aws-nodejs-typescript
Install required node packages for this project
npm install --save axios twitter-api-client
npm install --save-dev serverless-offline
axios: Promise based HTTP client for the browser and node.js
twitter-api-client Node.js client for Twitter API
serverless-offline This Serverless plugin emulates AWS λ and API Gateway on your local machine to speed up your development cycles.
Define your function in serverless.ts like this
import type { AWS } from '@serverless/typescript';
const serverlessConfiguration: AWS = {
service: 'twitter-bot',
frameworkVersion: '2',
custom: {
webpack: {
webpackConfig: './webpack.config.js',
includeModules: true
}
},
// Add the serverless-webpack plugin
plugins: ['serverless-webpack', 'serverless-offline'],
provider: {
name: 'aws',
runtime: 'nodejs14.x',
apiGateway: {
minimumCompressionSize: 1024,
},
environment: {
AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
},
},
functions: {
twitterJokesBot: {
handler: 'handler.twitterJokesBot',
events: [
{
http: {
method: 'get',
path: 'twitterJokesBot',
}
}
]
}
}
}
module.exports = serverlessConfiguration;
Here we have defined a function named twitterJokesBot
and it will be of type GET
Make sure that you add your serverless-offline
plugin to the list of plugins in serverless.ts
Define twitter-api-client
import { TwitterClient } from 'twitter-api-client';
export const twitterClient = new TwitterClient({
apiKey: process.env.TWITTER_API_KEY,
apiSecret: process.env.TWITTER_API_SECRET,
accessToken: process.env.TWITTER_ACCESS_TOKEN,
accessTokenSecret: process.env.TWITTER_ACCESS_SECRET,
});
Make sure that you have added these keys and tokens into your environment
Define joke functions
import Axios, { AxiosResponse } from "axios";
/**
* Get a joke from jokeapi.dev. If the length of tweet string is greater than 280 character then recurse till you find one.
* @returns string
*/
export const getJokeTweet = async () => {
//List of hashtags for the tweet
const hashTags =
"@metacollective9 #jokes #javascript #programming #dev #linux #java #programming #python #reactjs #DataScience #infosec #gamedev #BigData #serverless";
const footerText = "From https://jokeapi.dev";
//Get a random joke from jokeapi
let joke: AxiosResponse = await Axios.get(
"https://v2.jokeapi.dev/joke/Programming?blacklistFlags=nsfw,religious,political,racist,sexist,explicit&type=single"
);
// \n will add line breaks to the tweet
const tweet = `${joke.data.joke} \n\n ${hashTags} \n\n ${footerText}`;
console.log(tweet.length);
if (tweet.length <= 280) {
return tweet;
}
return await getJokeTweet();
};
/**
* Get a gif image from giphy.com
* @returns image buffer
*/
export const getJokeImage = async () => {
//get a giphy to go with this joke
let giphy: AxiosResponse = await Axios.get(
`https://api.giphy.com/v1/gifs/random?api_key=${process.env.GIPHY_API_KEY}&tag=bad+joke&rating=g`
);
//Get that giphy image as a buffer.
const image: AxiosResponse = await Axios.get(giphy?.data.data.images.downsized_medium.url, {
responseType: "arraybuffer",
});
return image;
};
There are two parts of this
-
getJokeTweet
is to get a random joke fromjokeapi.dev
, then adds your hashtags and other texts that you want to attach with this tweet. It also checks that it is not more than 280 characters (tweet character limit as of Feb 2022), if it is then recurse and gets another joke Lookout forblacklistFlags
in the API call. This makes sure that you get a nice & clean joke -
getJokeImage
is to get a random giphy image using the giphy api keys we got earlier. You have to get it as anarraybuffer
so that we can upload it to twitter as abase64
image
Put them all together in your
handler.ts
import { APIGatewayProxyHandler } from "aws-lambda";
import "source-map-support/register";
import { twitterClient } from "./src/util/twitterApiClient";
import { getJokeImage, getJokeTweet } from "./src/util/joke";
import { AxiosResponse } from "axios";
import { MediaUpload } from "twitter-api-client";
export const twitterJokesBot: APIGatewayProxyHandler = async (_event, _context) => {
let tweet: string = "";
try {
//get Joke
tweet = await getJokeTweet();
const image: AxiosResponse = await getJokeImage();
//Upload media to twitter
const media: MediaUpload = await twitterClient.media.mediaUpload({
media: Buffer.from(image.data, "binary").toString("base64"),
});
//Send a tweet with joke and media
await twitterClient.tweets.statusesUpdate({
status: tweet,
media_ids: media.media_id_string,
});
} catch (error) {
console.log(error);
}
return {
statusCode: 200,
body: JSON.stringify(
{
joke: tweet,
length: tweet.length
},
null,
2
),
};
};
This is also a 2 step process
- First is to upload a media asset to your twitter account
- Then use the
media_id_string
from the response of uploaded media and send the tweet with it
That's it, now you are all set to test it -
Run sls offline --stage local
in your terminal and you should have your endpoint ready to test with like this
🎉🎉🎉 Your bot is ready to launch.
If you wish to deploy it to your AWS account, then set your AWS Access Key & AWS secret Key in the environment and run sls deploy --stage dev
You can get the entire example from this repository https://github.com/appletreeat56/twitter-bot
Posted on February 15, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.