Writing an experimental Twitter Bot
by Alina Vretinaris and Thomas Reinecke

Social Media gained a lot of importance for business in the last years. The internet made information more accessible and they became an invaluable crude material for companies of any industry. As part of my last internship in a development department of my cooperate studying partner I was asked to write an experimental Twitter bot. We, my supervisor and I, have been curious to see out how easy it was to build a bot that autonomously acts in parallel but independently from the actual account-owning human, to increase the users social reach and influence. The most important indicators for measuring success were the amount of followers and the number of impressions that were generated.
Planning the Bot
The first thing we were thinking was about how we wanted the bot to be perceived by others. We decided, the bot should not be recognisable as such, we were looking for some sort of stealth mode since we did not wanted to influence others by the fact of interacting with an algorithm. We also did not plan to implement a fancy AI behind the bot, more a relatively simple ruleset. To create a natural perception, we decided to build a hybrid, where the human who’s owning the twitter account is sharing it with the bot. We planned the bot to complement the human user.
Our first goal was to increase the attention an account gets from other user on twitter. There are some functions twitter provides to drive that:
- Tweet: this is somewhat difficult to implement as you would need an AI that was able to build correct and interesting sentences. We haven’t considered this function as an option in this pilot.
- Retweet: You can replicate content from other twitter users in two different ways: You can replicate it as exact copy. Or you can replicate a tweet and add a personal comment. Quoted tweets are also difficult to produce as you would need also some algorithm or AI that was able to produce thematically reasonable replies. Retweeting without an additional comment is certainly an option. Retweeting something even can draw the attention of the original author to your account as he will receive a message that his tweet was retweeted by you.
- Like: Another function that does not need greater cognitive abilities but draws the attention of the original author to you as he will also receive a message that you liked his tweet.
- Follow: You can follow another user on Twitter. This is certainly one of the strongest drivers to gain attention and to encourage “follow back”
Our next idea was to define Timeslots in which the bot should be active and perform several activities. This brings two mayor advantages. First, we do not want the Bot to be a Spambot. The timeslots prevent the Bot from posting too much content and from posting content during unusual times. The Bot is active every five minutes. In an hour it can perform a maximum of 12 actions. Second the user can define the times when the bot should be active. That means the Bot can be personalized to a user. If the user is active usually during afternoon and late in the night, this user can set the timeslots of its bot to afternoon and late in the night. This way the bot will not be detected by unusual activity of the account.
Implementation
We decided to write the bot in JavaScript and use NodeJS since there are a number of great node packages out there that allow to access the twitter API easily. We decided for this one:
https://www.npmjs.com/package/twit
Build the Backlog
Twitter provides different endpoints that enable your app to collect tweets according to Hashtags you defined. You can use the Get function that is provided through the REST API or you can use the Streaming API to filter real time tweets. We decided to use the streaming API to collect the desired tweets.
We initialised the streaming API with a collection of hashtags we are interested in and defined the endpoints for several events:
const initStream = (tags) => {
if (tags && Array.isArray(tags) && tags.length) {
params.track = tags;
stream = twitter.stream('statuses/filter', params);
stream.on('tweet', onTweet);
stream.on('message', onMessage);
stream.on('delete', onDelete);
stream.on('limit', onLimit);
stream.on('disconnect', onDisconnect);
stream.on('connect', onConnect);
stream.on('connected', onConnected);
stream.on('reconnect', onReconnect);
stream.on('warning', onWarning);
}
};To reduce the likeliness of distributing senseless, uninteresting, boring or inappropriate content, we built a filter that only stores a tweet if it has more than 200 likes and retweets. A tweet matching this requirement it getting stored with some additional attributes in a HashMap. The additional attributes are :
- tweetId — unique ID every tweet receives when it was posted. With this ID our Bot is able to react to the tweet and process a like or a retweet
- name — name of the user who posted the tweet is important because this user might be interesting to follow.
- created_at — this attribute shows the date when the tweet was created. the attribute is not used yet by the bot but may be interesting for better filtering if we want the most recent tweets in the backlog to be used for a like or retweet action
- Text — This attribute is also not used yet, but a more sophisticated version of the bot could use this attribute to analyse the text with natural language processing and add quoted tweets to the portfolio of the bot.
- Likes/retweets — Both attributes show the amount of likes and retweets the tweet received yet. This is important because the bot decides which action to process with a tweet according to this numbers
- usersFollower/usersFriends — The first attribute shows the amount of follower the user who posted the tweet has. The second attribute shows how many accounts the user who posted the tweet follows. These numbers are important as because of them the Bot decides if an account is interesting to follow or not
- Action/follow — These attributes are undefined when a tweet gets stored in the backlog. Every five minutes the Bot runs over its backlog and assigns actions to the tweets that are not assigned to an action yet and decides if the author of the tweet is interesting to follow or not
- Timestamp — This attribute stores the date when a tweet gets stored in the backlog. This is important because we want the bot to delete tweets from the backlog if they exceeded a pre-configured timeframe. This is to ensure that the backlog does not contain too much tweets, that are not interesting anymore and only slow down the Bots performance.
As tweets get retweeted and liked thousands of times they appear again and again in the stream and the bot may store them again in the Backlog if it misses them in the first place when our storage requirements are not met yet.
After a pre-configured number of hours (48 hours at the moment) a tweet gets deleted from the backlog in order to have the most recent tweets in the backlog.
Timeslots & Behaviour configuration
The timeslots help the user to define the bot activity hours on a single day, these can be split into multiple slices. In addition, the user is able to define a minimum amount and a maximum amount of likes he wants the bot to process. Same case with the retweets the user wants the bot to process per day. This is to give the Bot more credibility as each day it processes a random amount of actions that it calculates with the information given by the user.
For example, I as a user want the Bot to perform a minimum of 3 likes per day but a maximum of 10. The Bot calculates now every day a random amount of likes between 3 and 10. Then it processes an algorithm to distribute the amount of likes evenly on the timeslots. It processes the same procedure with the calculated amount of retweets and follow actions although the follow actions don’t have a minimum. There may be a day when the bot does not process a follow action. This is to prevent the Bot following too much people. And a human user does not follow other accounts every day either.
Action Assignment
The Algorithm that is controlling the activity of the bot works like this:
- We have the amount of likes and retweets that the bot calculated to process for this day, e.g. Likes=7, Retweets=10, these two numbers get summed up into 17 potential actions

- This amount of actions will be assigned randomly to the timeslots:
Slot-1: 7 Actions, Slot-2 : 4 Actions, Slot-3 : 6 Actions

- After assigning actions to the timeslot the Bot now first assigns the likes to the timeslots. It assigns half of the actions of the first timeslot to be likes. In this case 3 actions of the first timeslot will be likes. Then it reduces this amount from the whole amount of likes to process this day.



- this procedure is repeated for Retweet distribution. The association of actions into timeslots would look like this finally:

Now all the actions are assigned to a timeslot and can be processed when the Bot gets active in this timeslot.
Action Execution
Every 5 minutes the Bot checks if it is currently running in one of the pre-configure timeslots. If so, it has to decide if it wants to process a like or a retweet and it processes one follow action until there are no follow, like or retweet actions left for this timeslot.
Like or Retweet action
The Bot decides what action to perform by randomly picking one of them. Picking for Like, it calls the function nextLike() which calculates the next tweet the bot is supposed to like from the actual Tweet backlog and then executes the like:
twitter.post('favorites/create', { id: next.tweetId } , (err) => {
});Picking for Retweet, it will call the function nextRetweet() (which works very similar to nextLike())
twitter.post('statuses/retweet/:id', {id: next.tweetId}, (err) => {
});Follow action
The bot checks if any follow actions are left for this timeslot. If so it calls the function follow().
This function calculates the tweets, that were posted by an user, who has a difference between the number of its followers and the number of its friends of less than 10 percent. It chooses the user with the highest number of friends to follow next. If the bot decided to follow another user it flags the tweets follow attribute in the backlog to ‘processed’ and stores a user reference as foundation for unfollow()
twitter.post('friendships/create', { screen_name: next.name } , (err) => {});Unfollow action
The user(s) that were followed by the bot will be stored in a database and the list is inspected every day to find potential candidates for unfollow. We decided to implement unfollow to make sure the number of “I follow” and “Followers” is not drifting apart too much. We decided to give users a month of time to follow back before they become subject of “unfollow”. In Addition, the Bot checks every Morning if it was followed by another user and follows this user back.
Outcome
The bot was just set live. We’re going to study it over the next weeks and come back with results in this article at a later time. Stay tuned
Originally published at medium.com on September 3, 2018.
