Twitter Status IDs and Direct Message IDs

twitter-birdI recently created a Magic Eight Ball twitter-bot as a demo. Written in Python using the python-twitter API wrapper, it runs every 2 minutes and polls twitter for new replies (status updates containing @osric8ball) and direct messages (DMs) to osric8ball. If there are any, it replies with a random 8-Ball response.

Every status update and DM has an associated numeric ID. Initially, I stored the highest ID in a log file and used that when I polled twitter (i.e. “retrieve all replies and DMs with ID > highest ID”). However, I discovered that status updates and DMs apparently are stored in separate tables on twitter’s backend, as they have a separate set of IDs. Since the highest status ID was an order of magnitude larger than the highest DM ID, my bot completely ignored all DMs. This was not entirely obvious at first, as the IDs looked very similar, other than an extra digit: 2950029179 and 273876291.

My fix for this was to store both the highest status update ID and the highest DM ID is separate log files.

Another interesting twist: you have to be a follower of a user in order to send that user a DM.
At first I thought I had solved this by telling the bot to follow anyone who sent it a message. However, if you submit an API request to follow a user whom you are already following, it produces an error. So I added a check to see if the bot was already following the user, and, if not, follow the user.

In case anyone is interested, the entire code is below:

import twitter
import random

replyfile = 'twitterreply.log'
dmfile = 'twitterdm.log'
last_id = 0

api = twitter.Api(username='osric8ball', password='[actualpassword]')

friends = api.GetFriends()

responses = ['Signs Point To Yes','Yes','You May Rely On It','Ask Again Later','Concentrate And Ask Again','Outlook Good','My Sources Say No','Better Not Tell You Now','Without A Doubt','Reply Hazy, Try Again','It Is Decidedly So','Cannot Predict Now','My Reply Is No','As I See It Yes','It Is Certain','Yes Definitely','Don\'t Count On It','Most Likely','Very Doubtful','Outlook Not So Good']

def areWeFriends(screen_name):
isFriend = 0
for friend in friends:
if friend.screen_name == screen_name:
isFriend = 1
return isFriend

def makeFriend(screen_name):
if areWeFriends(screen_name) == 0:

def sendReply(screen_name):
response = responses[random.randint(0,19)]
api.PostUpdates('@' + screen_name + ': ' + response)
print '@' + screen_name + ': ' + response

def sendDirectMessage(screen_name):
response = responses[random.randint(0,19)]
print 'd ' + screen_name + ': ' + response

#Read logs
log = open(replyfile, 'r')
last_reply_id =

log = open(dmfile, 'r')
last_dm_id =

if last_reply_id > 0 and last_dm_id > 0:

#Get replies and direct messages
replies = api.GetReplies(since_id=last_reply_id)
directMessages = api.GetDirectMessages(since_id=last_dm_id)

#Update logs
if directMessages != []:
last_dm_id = directMessages[0].id

if replies != []:
last_reply_id = replies[0].id

if last_reply_id > 0:
log = open(replyfile,'w')
log.write( str(last_reply_id) )

if last_dm_id > 0:
log = open(dmfile,'w')
log.write( str(last_dm_id) )

# Loop through replies
for reply in replies:

# Loop through direct messages
for directMessage in directMessages:

print 'Unable to read ' + replyfile + ' or ' + dmfile

One thought on “Twitter Status IDs and Direct Message IDs”

Leave a Reply

Your email address will not be published. Required fields are marked *