< All posts | Fediverse | RSS | GitHub | Talks

Jan 19 2014

Super Easy Twitter Bots

I often get really quite mad ideas on writing twitter bots, But I often get pretty bored of doing all of the boiler plate that is required when wanting to achieve these things.

The typical process to making a twitter bot (in the language you want to use) is to:

* Make a twitter account
* Get the dev details
* Find a twitter library for the language you want to use
* Make sure the API is API version 1.1 else it won't work
* Try and get that to work
* Make a polling system that works
* Reply to people
* Done

Since I am typically plagued by finding API’s that work and function like they tell me they do, I have come up with a new way of writing bots that is easy to do in any language (as long as it can read env vars) and also send back replies. It learns from a trick that is now (mostly) gone from the modern HTTP world.

The history of CGI

Back in the day if you wanted dynamic content in your web server, You standard goto route would be to write a perl script and use the CGI system that was in any good web server.

When a Classic CGI webserver got a request for dynamic content it would spin up a new process of your desired script, the script would be provided the information on stuff like requesting IP addresses and URL requested. If the user had posted things it would be fed in through stdin. Then what ever the script pushed out would be what was pushed out to the client, HTTP headers and all.

This meant two things, It was very easy to write CGI servers. It also meant that you could (if you wanted to) write dynamic web content with just a few bash scripts. Allowing anything that could run from a shell and could read shell env vars, able to act as content providers for websites.

CGI for twitter

After realising that this use module is what I could do for twitter bots, I started to make twitterd. A twitter deamon that will listen on the twitter streaming API. And depending on its setup, when mentioned or @‘td, Almost instantly A process would be spawned with the env vars of what was needed, and anything (if the script did output anything) would be the twitter response. This meant I now had the ability to write a twitter bot in anything I wanted with out the source program being even aware that it is a twitter bot.

The new setup process

So for this example I just want to make a Twitter bot that will respond to me with the tweetID that I just @‘td it with.

So first I will make a new twitter account, then sign up for a dev application, Generate oauth creds for that account. so now I have 4 strings I need to put into twitterd.

At this point I will just download a precompiled version of twitterd (Or if you have Go, compile it yourself) and launch it for the first time.

$ twitterd
2014/01/20 13:57:17 Twitterd Started
2014/01/20 13:57:17 Built config file. please fill it in.

I will see that two new things have been created,

.twitterconfig.json - The config file for twitterd CGI - A directory where all the CGI scripts will be launched from.

The configuration file is as follows:

{
  "Username": "Fillmein",
  "ConsumerKey": "Fillmein",
  "ConsumerSecret": "Fillmein",
  "AccessToken": "Fillmein",
  "AccessSecret": "Fillmein",
  "StreamTarget": "default",
  "EnableReply": true,
  "EnableMention": false,
  "EnableReplyMention": false
}

Filling in the first 5 things with the information I have is easy. For now we will not touch anything else in the config file.

Since EnableReply is enabled by default every time the bot is @‘td it will attempt to launch a file called reply (or reply.exe if you are on windows) and if the script responds with anything, Twitterd will automatically add “@person who triggered the script” and then with whatever the script outputted.

There are (currently) 4 things that twitterd gives scripts to play with:

declare -x tweet_id="424612189752659969" # The ID of the tweet that triggered it
declare -x tweet_src="benjojo" # The twitter name of the person who triggered it
declare -x tweet_src_nomention="hello world" # The tweet that triggered it with the first "word" removed
declare -x tweet_text="@testbot hello world" # The full tweet that triggered it.

so in my script, since I only want to reply with the tweetID. I will make this simple bash script:

#!/bin/bash
echo -n $tweet_id

and then mark it as executable by doing chmod +x reply

Then whenever someone directly @‘ts the bot, This script will be launched, if the script prints anything from stdout. that will be the reply of the tweet.

More advanced usage

If we set EnableMention to be true, then anything that comes in to the stream (by default the stream is set to only listen for anything that contains @username_of_bot) will trigger the script CGI/mention

If we change StreamTarget to be something that we want to keep an eye out for, Each time the word that is set in StreamTarget then the CGI/mention script will be triggered with the same set of env vars that the reply script had.

If we wanted to log all the mentions of ducks on Twitter, we could setup the config to be like

{
  "Username": "Fillmein",
  "ConsumerKey": "Fillmein",
  "ConsumerSecret": "Fillmein",
  "AccessToken": "Fillmein",
  "AccessSecret": "Fillmein",
  "StreamTarget": "ducks",
  "EnableReply": false,
  "EnableMention": true,
  "EnableReplyMention": false
}

And then to log down all of them we can have a bash script in CGI/mention to be

#!/bin/bash
echo -n $tweet_id $tweet_src $tweet_text >> DuckLog.log

And then every time ducks is mentioned on twitter, it will be appended to DuckLog.log.

I finally hope that this is a great demo on how easy twitter bots should be to make! You can find twitterd on my Github if you like what I do you can star the repo and Follow me on github