-
Notifications
You must be signed in to change notification settings - Fork 0
/
twitterbot.py
216 lines (168 loc) · 7.1 KB
/
twitterbot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
#!/usr/bin/python
#
# 12tweet - tiny little robots that live in the twittersphere
# Created by Jeff Verkoeyen @featherless
#
# The shell of a twitter bot; you supply the brains.
#
# The standard bot automatically populates your db with users
# who are following you, and deactivating those who aren't
# anymore.
#
# === Example ===
#
# bot = twitterbot.StandardBot(dbuser='dbusername', ...)
#
# tweets = bot.getTweets()
# # Work on your tweets
# bot.commitTweets() # Update config's last_reply_id
#
import sys
import twitter
import MySQLdb
import settings
class StandardBot(object):
'''A twitter bot.
'''
def __init__(self, dbuser, dbpass, dbdb, twituser, twitpass):
try:
self.conn = MySQLdb.connect(host = "localhost",
user = dbuser,
passwd = dbpass,
db = dbdb)
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args[0], e.args[1])
sys.exit(1)
self.cursor = self.conn.cursor()
self.twituser = twituser
self.twitpass = twitpass
#cursor.execute("SELECT VERSION()")
#row = self.cursor.fetchone()
#print "server version:", row[0]
################################
# Get the last reply id.
self.cursor.execute("SELECT value FROM config WHERE name=%s", ('last_reply_id'))
row = self.cursor.fetchone()
if row is None:
self.cursor.execute("INSERT INTO config(name) VALUES(%s)", ('last_reply_id'))
self.last_reply_id = None
else:
self.last_reply_id = row[0]
################################
# Initialize the sets of users.
self.existing_users = {}
self.disabled_users = {}
self.current_users = {}
self.new_users = {}
self.updateUserLists()
'''Implement this function in your class to override
the message.
'''
def msgWelcomeNewUser(self, screen_name):
self.notifyUser(screen_name, "Thanks for following another 1-2-tweet bot! Find more at http://12tweet.com/")
'''Implement this function in your class to override
the message.
'''
def msgWelcomeBackUser(self, screen_name):
self.notifyUser(screen_name, "Welcome back! We've kept your profile safely tucked away")
'''Implement this function in your class if you have
other parameters stored in the user row.
'''
def dbToUser(self, row):
return {
'id': row[0],
'screen_name': row[1],
'active': row[2],
'is_admin': row[3]}
def updateUserLists(self):
################################
# Get all existing followers.
self.cursor.execute("SELECT * FROM followers")
rows = self.cursor.fetchall()
if len(rows) == 0:
print "Nobody listed yet"
else:
# This will add the user either to existing_users or disabled_users
for row in rows:
user = self.dbToUser(row)
self.addExistingUser(user, user['screen_name'], user['active'])
################################
# Fetch all of the followers
# from twitter.
self.api = twitter.Api(self.twituser, self.twitpass)
if settings.in_dev:
self.api.SetCache(None)
# F1nd_P4sS10n864!
self.followers = self.api.GetFollowers()
################################
# Check for new followers
if len(self.followers) == 0:
print "No followers. How sad."
else:
# Add all users not currently registered to the new_users map
for user in self.followers:
self.current_users[user.screen_name] = True
if user.screen_name not in self.existing_users:
self.new_users[user.screen_name] = user
################################
# If we have new followers,
# add 'em to the db.
if len(self.new_users) > 0:
print "New users: " + str(len(self.new_users))
for screen_name in self.new_users:
if screen_name in self.disabled_users:
print "Reactivating " + screen_name
self.cursor.execute("UPDATE followers SET active=1 WHERE screen_name=%s", (screen_name))
self.msgWelcomeBackUser(screen_name)
user = self.disabled_users[screen_name]
del self.disabled_users[screen_name]
self.existing_users[screen_name] = user
else:
print "Adding " + screen_name
self.cursor.execute("INSERT INTO followers(screen_name) VALUES(%s)", (screen_name))
self.cursor.execute("SELECT * FROM followers WHERE id=%s", (self.conn.insert_id()))
row = self.cursor.fetchone()
user = self.dbToUser(row)
self.addExistingUser(user, user['screen_name'], user['active'])
self.msgWelcomeNewUser(user['screen_name'])
################################
# Deactivate anyone that's not
# following anymore
newly_deactivated = {}
for screen_name in self.existing_users:
if screen_name not in self.current_users:
print "Deactivating user "+screen_name
newly_deactivated[screen_name] = True
self.cursor.execute("UPDATE followers SET active=0 WHERE screen_name=%s", (screen_name))
# The user has stopped following us, so they won't even see this update.
#notifyUser(screen_name, "Thanks for using another 1-2-tweet bot!")
# We move the users to the disabled map here because
# we can't remove elements from a map while traversing it
for screen_name in newly_deactivated:
user = self.existing_users[screen_name]
del self.existing_users[screen_name]
self.disabled_users[screen_name] = user
def notifyUser(self, screen_name, message):
print "@"+screen_name+" "+message
self.api.PostUpdate("@"+screen_name+" "+message)
def getTweets(self):
################################
# Start parsing the tweets
tweets = self.api.GetReplies(self.last_reply_id)
self.newest_id = self.last_reply_id
# Grab the newest id.
for tweet in reversed(tweets):
self.newest_id = tweet.id
return reversed(tweets)
def commitTweets(self):
if self.newest_id != self.last_reply_id:
print "Updating last_reply_id..."
self.cursor.execute("UPDATE config SET value=%s WHERE name=%s", (self.newest_id, 'last_reply_id'))
def addExistingUser(self, user, screen_name, enabled):
if enabled:
self.existing_users[screen_name] = user
else:
self.disabled_users[screen_name] = user
def printStats(self):
print "Existing: "+str([user for user in self.existing_users])
print "Disabled: "+str([user for user in self.disabled_users])