←︎ booster :: 624276b


1
commit 624276b81844714a8fde292489b879b4aa7da91b
2
Author: acidvegas <acid.vegas@acid.vegas>
3
Date:   Thu Jun 27 23:41:18 2019 -0400
4
5
    Initial commit
6
---
7
 LICENSE              |  15 +++++
8
 README.md            |  23 +++++++
9
 booster/booster.py   |  20 ++++++
10
 booster/config.py    |  26 ++++++++
11
 booster/debug.py     |  93 ++++++++++++++++++++++++++++
12
 booster/functions.py |  23 +++++++
13
 booster/twitter.py   | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++
14
 7 files changed, 368 insertions(+)
15
16
diff --git a/LICENSE b/LICENSE
17
new file mode 100644
18
index 0000000..69997e8
19
--- /dev/null
20
+++ b/LICENSE
21
@@ -0,0 +1,15 @@
22
+ISC License
23
+
24
+Copyright (c) 2019, acidvegas <acid.vegas@acid.vegas>
25
+
26
+Permission to use, copy, modify, and/or distribute this software for any
27
+purpose with or without fee is hereby granted, provided that the above
28
+copyright notice and this permission notice appear in all copies.
29
+
30
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
31
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
32
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
33
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
34
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
35
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
36
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
37
diff --git a/README.md b/README.md
38
new file mode 100644
39
index 0000000..2a46e03
40
--- /dev/null
41
+++ b/README.md
42
@@ -0,0 +1,23 @@
43
+###### Requirments
44
+* [Tweepy](http://pypi.python.org/pypi/tweepy)
45
+
46
+###### Instructions
47
+Register a Twitter account, and [sign up](http://dev.twitter.com/apps/new) for a new developer application.
48
+
49
+Go to your new application settings "Keys and Access Tokens" tab.
50
+
51
+Click the "Create Your Access Token" button on the bottom.
52
+
53
+These will be used in the config to connect to your Twitter account.
54
+
55
+Go to your new application settings "Permissions".
56
+
57
+Change your access to "Read, Write and Access direct messages".
58
+
59
+Edit your `config.py` and change the Twitter API settings.
60
+
61
+###### Mirrors
62
+- [acid.vegas](https://acid.vegas/booster) *(main)*
63
+- [SuperNETs](https://git.supernets.org/acidvegas/booster)
64
+- [GitHub](https://github.com/acidvegas/booster)
65
+- [GitLab](https://gitlab.com/acidvegas/booster)
66
diff --git a/booster/booster.py b/booster/booster.py
67
new file mode 100644
68
index 0000000..d28b7d2
69
--- /dev/null
70
+++ b/booster/booster.py
71
@@ -0,0 +1,20 @@
72
+#!/usr/bin/env python
73
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
74
+# booster.py
75
+
76
+import sys
77
+
78
+sys.dont_write_bytecode = True
79
+
80
+import debug
81
+
82
+debug.info()
83
+if not debug.check_version(3):
84
+    debug.error_exit('Requires Python version 3 to run!')
85
+if debug.check_privileges():
86
+    debug.error_exit('Do not run as admin/root!')
87
+debug.check_imports()
88
+debug.check_config()
89
+import twitter
90
+twitter.Booster().run()
91
+debug.keep_alive()
92
diff --git a/booster/config.py b/booster/config.py
93
new file mode 100644
94
index 0000000..0a9a261
95
--- /dev/null
96
+++ b/booster/config.py
97
@@ -0,0 +1,26 @@
98
+#!/usr/bin/env python
99
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
100
+# config.py
101
+
102
+# API Settings
103
+consumer_key        = 'CHANGEME'
104
+consumer_secret     = 'CHANGEME'
105
+access_token        = 'CHANGEME'
106
+access_token_secret = 'CHANGEME'
107
+
108
+# Boost Keywords
109
+boost_keywords = ['500aday','autofollow','autofollowback','f4f','follow','follow4follow','followback','followtrain','instantfollow','instantfollowback','teamfollowback','wefollowback']
110
+
111
+# Throttling
112
+max_favorites = 75  # Only use up to 100  to avoid suspension.
113
+max_follows   = 75  # Only use up to 100  to avoid suspension.
114
+max_messages  = 750 # Only use up to 1000 to avoid suspension.
115
+max_tweets    = 750 # Only use up to 1000 to avoid suspension.
116
+max_unfollows = 75  # Only use up to 100  to avoid suspension.
117
+
118
+# Messaging
119
+send_message = False # Send a message to anyone who follows you.
120
+message      = 'Thank you for following our Twitter account!'
121
+
122
+# Where On Earth ID's (http://www.woeidlookup.com/)
123
+woeid = 23424975 # United States
124
diff --git a/booster/debug.py b/booster/debug.py
125
new file mode 100644
126
index 0000000..904f181
127
--- /dev/null
128
+++ b/booster/debug.py
129
@@ -0,0 +1,93 @@
130
+#!/usr/bin/env python
131
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
132
+# debug.py
133
+
134
+import ctypes
135
+import os
136
+import sys
137
+import time
138
+
139
+import config
140
+
141
+def action(msg):
142
+    print('%s | [#] - %s' % (get_time(), msg))
143
+
144
+def alert(msg):
145
+    print('%s | [+] - %s' % (get_time(), msg))
146
+
147
+def check_config():
148
+    for item in (config.consumer_key, config.consumer_secret, config.access_token, config.access_token_secret):
149
+        if item == 'CHANGEME':
150
+            error_exit('Edit your config file!')
151
+
152
+def check_imports():
153
+    try:
154
+        import tweepy
155
+    except ImportError:
156
+        error_exit('Failed to import the Tweepy library! (http://pypi.python.org/pypi/tweepy)')
157
+
158
+def check_privileges():
159
+    if check_windows():
160
+        if ctypes.windll.shell32.IsUserAnAdmin() != 0:
161
+            return True
162
+        else:
163
+            return False
164
+    else:
165
+        if os.getuid() == 0 or os.geteuid() == 0:
166
+            return True
167
+        else:
168
+            return False
169
+
170
+def check_version(major):
171
+    if sys.version_info.major == major:
172
+        return True
173
+    else:
174
+        return False
175
+
176
+def check_windows():
177
+    if os.name == 'nt':
178
+        return True
179
+    else:
180
+        return False
181
+
182
+def clear():
183
+    if check_windows():
184
+        os.system('cls')
185
+    else:
186
+        os.system('clear')
187
+
188
+def error(msg, reason=None):
189
+    if reason:
190
+        print('%s | [!] - %s (%s)' % (get_time(), msg, str(reason)))
191
+    else:
192
+        print('%s | [!] - %s' % (get_time(), msg))
193
+
194
+def error_exit(msg):
195
+    raise SystemExit('%s | [!] - %s' % (get_time(), msg))
196
+
197
+def get_time():
198
+    return time.strftime('%I:%M:%S')
199
+
200
+def get_windows():
201
+    if os.name == 'nt':
202
+        return True
203
+    else:
204
+        return False
205
+
206
+def info():
207
+    clear()
208
+    print(''.rjust(56, '#'))
209
+    print('#{0}#'.format(''.center(54)))
210
+    print('#{0}#'.format('Booster Twitter Bot'.center(54)))
211
+    print('#{0}#'.format('Developed by acidvegas in Python 3'.center(54)))
212
+    print('#{0}#'.format('https://acid.vegas/booster'.center(54)))
213
+    print('#{0}#'.format(''.center(54)))
214
+    print(''.rjust(56, '#'))
215
+
216
+
217
+def keep_alive():
218
+    try:
219
+        while True:
220
+            input('')
221
+    except KeyboardInterrupt:
222
+        sys.exit()
223
diff --git a/booster/functions.py b/booster/functions.py
224
new file mode 100644
225
index 0000000..956cb06
226
--- /dev/null
227
+++ b/booster/functions.py
228
@@ -0,0 +1,23 @@
229
+#!/usr/bin/env python
230
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
231
+# functions.py
232
+
233
+import datetime
234
+import random
235
+import urllib.request
236
+
237
+def get_day():
238
+    return datetime.datetime.today().weekday()
239
+
240
+def get_source(url):
241
+    req = urllib.request.Request(url)
242
+    req.add_header('User-Agent', 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)')
243
+    source  = urllib.request.urlopen(req, timeout=10)
244
+    charset = source.headers.get_content_charset()
245
+    if charset:
246
+        return source.read().decode(charset)
247
+    else:
248
+        return source.read().decode()
249
+
250
+def random_int(min, max):
251
+    return random.randint(min, max)
252
diff --git a/booster/twitter.py b/booster/twitter.py
253
new file mode 100644
254
index 0000000..e2ba905
255
--- /dev/null
256
+++ b/booster/twitter.py
257
@@ -0,0 +1,168 @@
258
+#!/usr/bin/env python
259
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
260
+# twitter.py
261
+
262
+import random
263
+import threading
264
+import time
265
+
266
+import tweepy
267
+
268
+import config
269
+import debug
270
+import functions
271
+
272
+class Booster(object):
273
+    def __init__(self):
274
+        self.api           = None
275
+        self.me            = None
276
+        self.favorites     = 0
277
+        self.max_favorites = config.max_favorites
278
+        self.follows       = 0
279
+        self.max_follows   = config.max_follows
280
+        self.messages      = 0
281
+        self.max_messages  = config.max_messages
282
+        self.tweets        = 0
283
+        self.max_tweets    = config.max_tweets
284
+        self.unfollows     = 0
285
+        self.max_unfollows = config.max_unfollows
286
+        self.send_message  = config.send_message
287
+        self.message       = config.message
288
+
289
+    def run(self):
290
+        self.login()
291
+        threading.Thread(target=self.loop_boost).start()
292
+        threading.Thread(target=self.loop_favorite).start()
293
+        threading.Thread(target=self.loop_follow).start()
294
+        threading.Thread(target=self.loop_search).start()
295
+#        threading.Thread(target=self.loop_trend).start()
296
+
297
+    def login(self):
298
+        try:
299
+            auth = tweepy.OAuthHandler(config.consumer_key, config.consumer_secret)
300
+            auth.set_access_token(config.access_token, config.access_token_secret)
301
+            self.api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
302
+            self.me  = self.api.me()
303
+        except tweepy.TweepError as ex:
304
+            debug.error_exit('Failed to login to Twitter! ({0})'.format(str(ex)))
305
+
306
+    def loop_boost(self):
307
+        while True:
308
+            try:
309
+                if 'boost_tweet' in locals(): self.api.destroy_status(boost_tweet.id)
310
+                boost_tweet = self.api.update_status('RT for followers! #' + ' #'.join(config.boost_keywords))
311
+                self.tweets += 1
312
+                debug.alert('Re-posted boost tweet.')
313
+            except tweepy.TweepError as ex:
314
+                debug.error('Error occured in the boost loop', ex)
315
+            finally:
316
+                random.shuffle(config.boost_keywords)
317
+                time.sleep(60*5)
318
+
319
+    def loop_favorite(self):
320
+        while True:
321
+            try:
322
+                for tweet in tweepy.Cursor(api.home_timeline, exclude_replies=True).items(50):
323
+                    if tweet.user.screen_name != me.screen_name:
324
+                        if not tweet.favorited:
325
+                            if random.choice((True, False, False, False, False)):
326
+                                api.create_favorite(tweet.id)
327
+                                self.favorites += 1
328
+                                debug.alert('Favorited a friends tweet!')
329
+                    time.sleep(30)
330
+            except tweepy.TweepError as ex:
331
+                debug.error('Error occured in the favorite loop!', ex)
332
+            finally:
333
+                time.sleep(60*15)
334
+
335
+    def loop_follow(self):
336
+        while True:
337
+            try:
338
+                followers   = api.followers_ids(me.screen_name)
339
+                friends     = api.friends_ids(me.screen_name)
340
+                non_friends = [friend for friend in followers if friend not in friends]
341
+                debug.action('Following back {0} supporters...'.format(len(non_friends)))
342
+                for follower in non_friends:
343
+                    api.create_friendship(follower)
344
+                    self.follows += 1
345
+                    debug.alert('Followed back a follower!')
346
+                    if self.follows >= self.max_follows:
347
+                        break
348
+                    if self.send_message:
349
+                        api.send_direct_message(screen_name=follower, text=self.message)
350
+                    time.sleep(30)
351
+            except tweepy.TweepError as ex:
352
+                debug.error('Error occured in the follow loop!', ex)
353
+            finally:
354
+                time.sleep(60*15)
355
+
356
+    def loop_search(self):
357
+        while True:
358
+            try:
359
+                query = random.choice(config.boost_keywords)
360
+                for item in api.search(q='#' + query, count=50, lang='en', result_type='recent'):
361
+                    if not item.user.following and not item.favorited:
362
+                        try:
363
+                            api.create_favorite(item.id)
364
+                            api.create_friendship(item.user.screen_name)
365
+                            self.favorites += 1
366
+                            self.follows += 1
367
+                            debug.alert('Followed a booster twitter!')
368
+                        except tweepy.TweepError as ex:
369
+                            debug.error('Unknown error occured in the search loop!', ex)
370
+                    time.sleep(30)
371
+            except tweepy.TweepError as ex:
372
+                debug.error('Error occured in the search loop!', ex)
373
+            finally:
374
+                time.sleep(60*15)
375
+
376
+    def loop_trend(self):
377
+        while True:
378
+            try:
379
+                trends    = self.api.trends_place(str(config.woeid))
380
+                hashtags = [x['name'] for x in trends[0]['trends'] if x['name'].startswith('#')]
381
+                for trend in hashtags:
382
+                    for item in self.api.search(q=trend, count=5, lang='en', result_type='top'):
383
+                        #self.api.update_status(item.tweet) # FIX THIS PART
384
+                        time.sleep(30)
385
+            except tweepy.TweepError as ex:
386
+                debug.error('Error occured in the trend loop!', ex)
387
+            finally:
388
+                time.sleep(60*15)
389
+
390
+    def loop_unfollow(self):
391
+        try:
392
+            followers   = self.api.followers_ids(self.me.screen_name)
393
+            friends     = self.api.friends_ids(self.me.screen_name)
394
+            non_friends = [friend for friend in friends if friend not in followers]
395
+            non_friends.reverse()
396
+            debug.action('Unfollowing {0} unsupporting friends...'.format(len(non_friends)))
397
+            for friend in non_friends:
398
+                self.api.destroy_friendship(friend)
399
+                self.unfollows += 1
400
+                debug.alert('Unfollowed an unsupporting friend!')
401
+                if self.unfollows == self.max_unfollows:
402
+                    break
403
+                else:
404
+                    time.sleep(60*functions.random_int(10,15))
405
+        except tweepy.TweepError as ex:
406
+            debug.error('Error occured in the unfollow loop!', ex)
407
+        finally:
408
+            self.unfollows = 0
409
+
410
+    def ratio_check(self):
411
+        if self.follows >= max_follows:
412
+            time.sleep(86400)
413
+        if me.friends_count >= 2000:
414
+            ratio = me.friends_count + (me.followers_count/10)
415
+            if me.friends_count >= ratio:
416
+                debug.action('Following to follower ratio is off! Starting the unfollow loop...')
417
+                unfollow_loop()
418
+
419
+    def stats(self):
420
+        debug.action('SceenName  : ' + self.me.screen_name)
421
+        debug.action('Registered : ' + self.me.created_at)
422
+        debug.action('Favorites  : ' + self.me.favourites_count)
423
+        debug.action('Following  : ' + self.me.friends_count)
424
+        debug.action('Followers  : ' + self.me.followers_count)
425
+        debug.action('Tweets     : ' + self.me.statuses_count)