1
1
# -*- coding: utf-8 -*-
2
2
3
3
"""
4
- Copyright 2014 Randal S. Olson
4
+ Copyright 2015 Randal S. Olson
5
5
6
6
This file is part of the Twitter Follow Bot library.
7
7
8
8
The Twitter Follow Bot library is free software: you can redistribute it and/or
9
9
modify it under the terms of the GNU General Public License as published by the
10
- Free Software Foundation, either version 3 of the License, or (at your option) any
11
- later version.
10
+ Free Software Foundation, either version 3 of the License, or (at your option)
11
+ any later version.
12
12
13
- The Twitter Follow Bot library is distributed in the hope that it will be useful,
14
- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15
- FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
+ The Twitter Follow Bot library is distributed in the hope that it will be
14
+ useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
16
+ License for more details.
16
17
17
- You should have received a copy of the GNU General Public License along with the Twitter
18
- Follow Bot library. If not, see http://www.gnu.org/licenses/.
18
+ You should have received a copy of the GNU General Public License along with
19
+ the Twitter Follow Bot library. If not, see http://www.gnu.org/licenses/.
19
20
"""
20
21
21
22
from twitter import Twitter , OAuth , TwitterHTTPError
28
29
CONSUMER_SECRET = ""
29
30
TWITTER_HANDLE = ""
30
31
31
- # put the full path and file name of the file you want to store your "already followed"
32
- # list in
33
- ALREADY_FOLLOWED_FILE = "already-followed.csv "
32
+ # put the full path and file name of the file you want to keep track of all
33
+ # the accounts you've ever followed
34
+ ALREADY_FOLLOWED_FILE = "already-followed.txt "
34
35
36
+ # put the full paths and file names of the files you want to keep track of
37
+ # your follows in
38
+ FOLLOWS_FILE = "following.txt"
39
+ FOLLOWERS_FILE = "followers.txt"
40
+
41
+ # make sure all of the sync files exist
42
+ for sync_file in [ALREADY_FOLLOWED_FILE , FOLLOWS_FILE , FOLLOWERS_FILE ]:
43
+ if not os .path .isfile (sync_file ):
44
+ with open (sync_file , "wb" ) as out_file :
45
+ out_file .write ("" )
46
+
47
+ # create an authorized connection to the Twitter API
35
48
t = Twitter (auth = OAuth (OAUTH_TOKEN , OAUTH_SECRET ,
36
- CONSUMER_KEY , CONSUMER_SECRET ))
49
+ CONSUMER_KEY , CONSUMER_SECRET ))
50
+
51
+
52
+ def sync_follows ():
53
+ """
54
+ Syncs the user's followers and follows locally so it isn't necessary
55
+ to repeatedly look them up via the Twitter API.
56
+
57
+ It is important to run this method at least daily so the bot is working
58
+ with a relatively up-to-date version of the user's follows.
59
+ """
60
+
61
+ # sync the user's followers (accounts following the user)
62
+ followers_status = t .followers .ids (screen_name = TWITTER_HANDLE )
63
+ followers = set (followers_status ["ids" ])
64
+ next_cursor = followers_status ["next_cursor" ]
65
+
66
+ with open (FOLLOWERS_FILE , "wb" ) as out_file :
67
+ for follower in followers :
68
+ out_file .write ("%s\n " % (follower ))
69
+
70
+ while next_cursor != 0 :
71
+ followers_status = t .followers .ids (
72
+ screen_name = TWITTER_HANDLE , cursor = next_cursor )
73
+ followers = set (followers_status ["ids" ])
74
+ next_cursor = followers_status ["next_cursor" ]
75
+
76
+ with open (FOLLOWERS_FILE , "ab" ) as out_file :
77
+ for follower in followers :
78
+ out_file .write ("%s\n " % (follower ))
79
+
80
+ # sync the user's follows (accounts the user is following)
81
+ following_status = t .friends .ids (screen_name = TWITTER_HANDLE )
82
+ following = set (following_status ["ids" ])
83
+ next_cursor = following_status ["next_cursor" ]
84
+
85
+ with open (ALREADY_FOLLOWED_FILE , "wb" ) as out_file :
86
+ for follow in following :
87
+ out_file .write ("%s\n " % (follow ))
88
+
89
+ while next_cursor != 0 :
90
+ following_status = t .friends .ids (
91
+ screen_name = TWITTER_HANDLE , cursor = next_cursor )
92
+ following = set (following_status ["ids" ])
93
+ next_cursor = following_status ["next_cursor" ]
94
+
95
+ with open (ALREADY_FOLLOWED_FILE , "ab" ) as out_file :
96
+ for follow in following :
97
+ out_file .write ("%s\n " % (follow ))
98
+
99
+
100
+ def get_do_not_follow_list ():
101
+ """
102
+ Returns the set of users the bot has already followed in the past.
103
+ """
104
+
105
+ dnf_list = []
106
+ with open (ALREADY_FOLLOWED_FILE , "rb" ) as in_file :
107
+ for line in in_file :
108
+ dnf_list .append (int (line ))
109
+
110
+ return set (dnf_list )
111
+
112
+
113
+ def get_followers_list ():
114
+ """
115
+ Returns the set of users that are currently following the user.
116
+ """
117
+
118
+ followers_list = []
119
+ with open (FOLLOWERS_FILE , "rb" ) as in_file :
120
+ for line in in_file :
121
+ followers_list .append (int (line ))
122
+
123
+ return set (followers_list )
124
+
125
+
126
+ def get_follows_list ():
127
+ """
128
+ Returns the set of users that the user is currently following.
129
+ """
130
+
131
+ follows_list = []
132
+ with open (FOLLOWS_FILE , "rb" ) as in_file :
133
+ for line in in_file :
134
+ follows_list .append (int (line ))
135
+
136
+ return set (follows_list )
37
137
38
138
39
139
def search_tweets (q , count = 100 , result_type = "recent" ):
40
140
"""
41
- Returns a list of tweets matching a certain phrase (hashtag, word, etc.)
141
+ Returns a list of tweets matching a phrase (hashtag, word, etc.).
42
142
"""
43
143
44
144
return t .search .tweets (q = q , result_type = result_type , count = count )
45
145
46
146
47
147
def auto_fav (q , count = 100 , result_type = "recent" ):
48
148
"""
49
- Favorites tweets that match a certain phrase (hashtag, word, etc.)
149
+ Favorites tweets that match a phrase (hashtag, word, etc.).
50
150
"""
51
151
52
152
result = search_tweets (q , count , result_type )
@@ -62,12 +162,13 @@ def auto_fav(q, count=100, result_type="recent"):
62
162
63
163
# when you have already favorited a tweet, this error is thrown
64
164
except TwitterHTTPError as e :
65
- print ("error: %s" % (str (e )))
165
+ if "you have already favorited this status" not in str (e ).lower ():
166
+ print ("error: %s" % (str (e )))
66
167
67
168
68
169
def auto_rt (q , count = 100 , result_type = "recent" ):
69
170
"""
70
- Retweets tweets that match a certain phrase (hashtag, word, etc.)
171
+ Retweets tweets that match a phrase (hashtag, word, etc.).
71
172
"""
72
173
73
174
result = search_tweets (q , count , result_type )
@@ -86,37 +187,13 @@ def auto_rt(q, count=100, result_type="recent"):
86
187
print ("error: %s" % (str (e )))
87
188
88
189
89
- def get_do_not_follow_list ():
90
- """
91
- Returns list of users the bot has already followed.
92
- """
93
-
94
- # make sure the "already followed" file exists
95
- if not os .path .isfile (ALREADY_FOLLOWED_FILE ):
96
- with open (ALREADY_FOLLOWED_FILE , "w" ) as out_file :
97
- out_file .write ("" )
98
-
99
- # read in the list of user IDs that the bot has already followed in the
100
- # past
101
- do_not_follow = set ()
102
- dnf_list = []
103
- with open (ALREADY_FOLLOWED_FILE ) as in_file :
104
- for line in in_file :
105
- dnf_list .append (int (line ))
106
-
107
- do_not_follow .update (set (dnf_list ))
108
- del dnf_list
109
-
110
- return do_not_follow
111
-
112
-
113
190
def auto_follow (q , count = 100 , result_type = "recent" ):
114
191
"""
115
- Follows anyone who tweets about a specific phrase (hashtag, word, etc.)
192
+ Follows anyone who tweets about a phrase (hashtag, word, etc.).
116
193
"""
117
194
118
195
result = search_tweets (q , count , result_type )
119
- following = set ( t . friends . ids ( screen_name = TWITTER_HANDLE )[ "ids" ] )
196
+ following = get_follows_list ( )
120
197
do_not_follow = get_do_not_follow_list ()
121
198
122
199
for tweet in result ["statuses" ]:
@@ -138,17 +215,18 @@ def auto_follow(q, count=100, result_type="recent"):
138
215
quit ()
139
216
140
217
141
- def auto_follow_followers_for_user (user_screen_name , count = 100 ):
218
+ def auto_follow_followers_of_user (user_screen_name , count = 100 ):
142
219
"""
143
- Follows the followers of a user
220
+ Follows the followers of a specified user.
144
221
"""
145
- following = set (t .friends .ids (screen_name = TWITTER_HANDLE )["ids" ])
146
- followers_for_user = set (t .followers .ids (screen_name = user_screen_name )["ids" ][:count ]);
222
+ following = get_follows_list ()
223
+ followers_of_user = set (
224
+ t .followers .ids (screen_name = user_screen_name )["ids" ][:count ])
147
225
do_not_follow = get_do_not_follow_list ()
148
-
149
- for user_id in followers_for_user :
226
+
227
+ for user_id in followers_of_user :
150
228
try :
151
- if (user_id not in following and
229
+ if (user_id not in following and
152
230
user_id not in do_not_follow ):
153
231
154
232
t .friendships .create (user_id = user_id , follow = False )
@@ -157,13 +235,14 @@ def auto_follow_followers_for_user(user_screen_name, count=100):
157
235
except TwitterHTTPError as e :
158
236
print ("error: %s" % (str (e )))
159
237
238
+
160
239
def auto_follow_followers ():
161
240
"""
162
- Follows back everyone who's followed you
241
+ Follows back everyone who's followed you.
163
242
"""
164
243
165
- following = set ( t . friends . ids ( screen_name = TWITTER_HANDLE )[ "ids" ] )
166
- followers = set ( t . followers . ids ( screen_name = TWITTER_HANDLE )[ "ids" ] )
244
+ following = get_follows_list ( )
245
+ followers = get_followers_list ( )
167
246
168
247
not_following_back = followers - following
169
248
@@ -176,34 +255,29 @@ def auto_follow_followers():
176
255
177
256
def auto_unfollow_nonfollowers ():
178
257
"""
179
- Unfollows everyone who hasn't followed you back
258
+ Unfollows everyone who hasn't followed you back.
180
259
"""
181
260
182
- following = set ( t . friends . ids ( screen_name = TWITTER_HANDLE )[ "ids" ] )
183
- followers = set ( t . followers . ids ( screen_name = TWITTER_HANDLE )[ "ids" ] )
261
+ following = get_follows_list ( )
262
+ followers = get_followers_list ( )
184
263
185
264
# put user IDs here that you want to keep following even if they don't
186
265
# follow you back
266
+ # you can look up Twitter account IDs here: http://gettwitterid.com
187
267
users_keep_following = set ([])
188
268
189
269
not_following_back = following - followers
190
270
191
- # make sure the "already followed" file exists
192
- if not os .path .isfile (ALREADY_FOLLOWED_FILE ):
193
- with open (ALREADY_FOLLOWED_FILE , "w" ) as out_file :
194
- out_file .write ("" )
195
-
196
271
# update the "already followed" file with users who didn't follow back
197
272
already_followed = set (not_following_back )
198
- af_list = []
273
+ already_followed_list = []
199
274
with open (ALREADY_FOLLOWED_FILE ) as in_file :
200
275
for line in in_file :
201
- af_list .append (int (line ))
276
+ already_followed_list .append (int (line ))
202
277
203
- already_followed .update (set (af_list ))
204
- del af_list
278
+ already_followed .update (set (already_followed_list ))
205
279
206
- with open (ALREADY_FOLLOWED_FILE , "w " ) as out_file :
280
+ with open (ALREADY_FOLLOWED_FILE , "wb " ) as out_file :
207
281
for val in already_followed :
208
282
out_file .write (str (val ) + "\n " )
209
283
@@ -215,17 +289,18 @@ def auto_unfollow_nonfollowers():
215
289
216
290
def auto_mute_following ():
217
291
"""
218
- Mutes everyone that you are following
292
+ Mutes everyone that you are following.
219
293
"""
220
- following = set ( t . friends . ids ( screen_name = TWITTER_HANDLE )[ "ids" ] )
294
+ following = get_follows_list ( )
221
295
muted = set (t .mutes .users .ids (screen_name = TWITTER_HANDLE )["ids" ])
222
296
223
297
not_muted = following - muted
224
298
225
299
# put user IDs of people you do not want to mute here
300
+ # you can look up Twitter account IDs here: http://gettwitterid.com
226
301
users_keep_unmuted = set ([])
227
-
228
- # mute all
302
+
303
+ # mute all
229
304
for user_id in not_muted :
230
305
if user_id not in users_keep_unmuted :
231
306
t .mutes .users .create (user_id = user_id )
@@ -234,14 +309,15 @@ def auto_mute_following():
234
309
235
310
def auto_unmute ():
236
311
"""
237
- Unmutes everyone that you have muted
312
+ Unmutes everyone that you have muted.
238
313
"""
239
314
muted = set (t .mutes .users .ids (screen_name = TWITTER_HANDLE )["ids" ])
240
315
241
316
# put user IDs of people you want to remain muted here
317
+ # you can look up Twitter account IDs here: http://gettwitterid.com
242
318
users_keep_muted = set ([])
243
-
244
- # mute all
319
+
320
+ # unmute all
245
321
for user_id in muted :
246
322
if user_id not in users_keep_muted :
247
323
t .mutes .users .destroy (user_id = user_id )
0 commit comments