Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Creating Your Own Whimsical Twitter Bot With Tracery

DZone's Guide to

Creating Your Own Whimsical Twitter Bot With Tracery

Read this fun article about how to create a Twitter bot with Tracery.

· AI Zone ·
Free Resource

Insight for I&O leaders on deploying AIOps platforms to enhance performance monitoring today. Read the Guide.

Inspired by a series of awesome Twitter bots that tweet seemingly random, but hilarious messages such as BoredElonMusk or thinkpiecebot, I set out to create some of my own. One that tweets random ideas for board games, and the other (that ties to a fiction project I’ve had in progress for some time) that tweets how the world ended. I didn’t want to spend too much time initially on the project, and someone recommended a site called cheapbotsdonequick.com, which does what its name implies, and is powered by Tracery, an open source Twitter bot library, meaning I could self-host when I was ready.

cheapbotsdonequick

Using the site to create and self-host your bot is incredibly easy; you log in with the Twitter account for your bot and add a string of JSON that represents the bot. Here’s the early code for BoardgameJerk:

{
"origin":"You are #you_are# #doing# #with_what# in #in#",
"you_are":["Dress makers","Farmers","Villagers","Warriors","Investigators","Fire fighters","Scientists","Explorers","Wine makers","Writers","Superheroes","Wizards","Ponies","Corporations","Factions","Cattle Herders","Civilizations","Soldiers","Knights", "Politicians", "Senators", "Generals","Clans","Vikings","Zombies","Cultists","Settlers","Sherlock Holmes","Meeples"],
"doing":["Exploring","Exploiting","Growing","Painting","Eating","Investigating","Fighting","Building","Trading","Delivering","Terraforming","Researching","Producing","Brewing","Protecting","Eating","Surviving","Escaping"],
"with_what":["Crops","Great Old Ones","Disease","Trains","Money","Territory","Ships","Sheep","Packages","Resources","Spaceships","Meeples","Cultists","Zombies","A Dragon","Detectives","Victory Points"],
"in":["Renaissance Italy","Medieval Europe","The Far East","Deep Space","Germany","North America","The Deepest Ocean","Wall Street","The 1920s","The Far Future","Mars","19th Century America","Ancient Greece","Ancient Rome","Ancient Egypt","Dungeons","Scotland","Australia"]
}

Tracery has a great tutorial that I won’t replicate here, but the syntax above is reasonably clear, the origin key contains the text with placeholders, and the other keys contain values that tracery randomly inserts into the placeholders. You might notice quickly that your bot might start committing grammar crimes, and while you can design your string to accommodate this, Tracery also has a series of modifiers to help. For example, for flexibility, I could remove the plural form of some of the text above, and instead use the .s modifier:

"origin": "You are #you_are.s# #doing# #with_what.s# in #in#",

When finished, you set how frequently the bot should tweet and click save.

Cheapbotsdonequick options

Self-Hosting

For many bots and their creators, this may be enough, but I was interested in self-hosting my bots so I could do more with them, such as re-purpose the same data model for other bot platforms and ideas, allow others to contribute to the data model, plus other ideas I haven’t had yet. I opted to use node.js and Heroku for mine, but of course, many other options are available.

Dependencies

First, add the dotenv, tracery-grammar, and twit NPM modules to your project. If you also decide to use Heroku, then you might find their CLI tool useful.

Vocabulary

I toyed with attempting to get all the bot vocabulary into one file, but ended up splitting it into three files for each list. I won't reproduce them all here, but you can see them in the project’s repository. I found the simplest way to add them as arrays was with a series of require statements:

let you_are =require('./you_are.json');
let doing =require('./doing.json');
let with_what =require('./with_what.json');
let in_place =require('./in.json');

Create Grammar

With the vocabulary in place, add it to Tracery, generate your tweet text, and add any modifiers from above:

constgrammar=tracery.createGrammar({
"you_are": you_are,
"doing": doing,
"with_what": with_what,
"in": in_place,
"origin":["You are #you_are# #doing# #with_what# in #in#"],
});

grammar.addModifiers(tracery.baseEngModifiers);

const tweet=grammar.flatten('#origin#');

Send Tweet

With the text ready to broadcast to the world, create a Twitter client and post your witticisms to the world. Running locally, I use keys provided by the dotenv module and a .env file, but running on Heroku, it uses config variables provided by the platform, but you can transition from one to the other without changing anything.

const T=newTwit(
{
        consumer_key:process.env.TWITTER_CONSUMER_KEY,
        consumer_secret:process.env.TWITTER_CONSUMER_SECRET,
        access_token:process.env.TWITTER_ACCESS_TOKEN,
        access_token_secret:process.env.TWITTER_ACCESS_TOKEN_SECRET
}
);

T.post('statuses/update',{status: tweet +" #boardgames"},(err,data,response)=>{
console.log(data)
});

Schedule Tweets

For now, I want the bot to tweet once a day, so I used the Heroku scheduler. It requires a shell script to run at each interval, so I created bin/run_bot.sh, which has one command:

#!/bin/bash
node index.js

Profit!

And that’s it! Once a day, my bot delivers wonderful words to all the boardgame fans of the internet, and I have a flexible code and vocabulary base for future features and other platforms.

Wonderful tweets

Enjoy, and see you at the gaming table!

TrueSight is an AIOps platform, powered by machine learning and analytics, that elevates IT operations to address multi-cloud complexity and the speed of digital transformation.

Topics:
twitter ,bots ,node ,random ,javascript ,tracery ,fiction ,artificial intelligence ,ai ,bot development

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}