🢀 booster :: 624276b


commit 624276b81844714a8fde292489b879b4aa7da91b
Author: acidvegas <acid.vegas@acid.vegas>
Date:   Thu Jun 27 23:41:18 2019 -0400

    Initial commit

diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..69997e8
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,15 @@
+ISC License
+
+Copyright (c) 2019, acidvegas <acid.vegas@acid.vegas>
+
+Permission to use, copy, modify, and/or distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..2a46e03
--- /dev/null
+++ b/README.md
@@ -0,0 +1,23 @@
+###### Requirments
+* [Tweepy](http://pypi.python.org/pypi/tweepy)
+
+###### Instructions
+Register a Twitter account, and [sign up](http://dev.twitter.com/apps/new) for a new developer application.
+
+Go to your new application settings "Keys and Access Tokens" tab.
+
+Click the "Create Your Access Token" button on the bottom.
+
+These will be used in the config to connect to your Twitter account.
+
+Go to your new application settings "Permissions".
+
+Change your access to "Read, Write and Access direct messages".
+
+Edit your `config.py` and change the Twitter API settings.
+
+###### Mirrors
+- [acid.vegas](https://acid.vegas/booster) *(main)*
+- [SuperNETs](https://git.supernets.org/acidvegas/booster)
+- [GitHub](https://github.com/acidvegas/booster)
+- [GitLab](https://gitlab.com/acidvegas/booster)
diff --git a/booster/booster.py b/booster/booster.py
new file mode 100644
index 0000000..d28b7d2
--- /dev/null
+++ b/booster/booster.py
@@ -0,0 +1,20 @@
+#!/usr/bin/env python
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
+# booster.py
+
+import sys
+
+sys.dont_write_bytecode = True
+
+import debug
+
+debug.info()
+if not debug.check_version(3):
+    debug.error_exit('Requires Python version 3 to run!')
+if debug.check_privileges():
+    debug.error_exit('Do not run as admin/root!')
+debug.check_imports()
+debug.check_config()
+import twitter
+twitter.Booster().run()
+debug.keep_alive()
diff --git a/booster/config.py b/booster/config.py
new file mode 100644
index 0000000..0a9a261
--- /dev/null
+++ b/booster/config.py
@@ -0,0 +1,26 @@
+#!/usr/bin/env python
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
+# config.py
+
+# API Settings
+consumer_key        = 'CHANGEME'
+consumer_secret     = 'CHANGEME'
+access_token        = 'CHANGEME'
+access_token_secret = 'CHANGEME'
+
+# Boost Keywords
+boost_keywords = ['500aday','autofollow','autofollowback','f4f','follow','follow4follow','followback','followtrain','instantfollow','instantfollowback','teamfollowback','wefollowback']
+
+# Throttling
+max_favorites = 75  # Only use up to 100  to avoid suspension.
+max_follows   = 75  # Only use up to 100  to avoid suspension.
+max_messages  = 750 # Only use up to 1000 to avoid suspension.
+max_tweets    = 750 # Only use up to 1000 to avoid suspension.
+max_unfollows = 75  # Only use up to 100  to avoid suspension.
+
+# Messaging
+send_message = False # Send a message to anyone who follows you.
+message      = 'Thank you for following our Twitter account!'
+
+# Where On Earth ID's (http://www.woeidlookup.com/)
+woeid = 23424975 # United States
diff --git a/booster/debug.py b/booster/debug.py
new file mode 100644
index 0000000..904f181
--- /dev/null
+++ b/booster/debug.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
+# debug.py
+
+import ctypes
+import os
+import sys
+import time
+
+import config
+
+def action(msg):
+    print('%s | [#] - %s' % (get_time(), msg))
+
+def alert(msg):
+    print('%s | [+] - %s' % (get_time(), msg))
+
+def check_config():
+    for item in (config.consumer_key, config.consumer_secret, config.access_token, config.access_token_secret):
+        if item == 'CHANGEME':
+            error_exit('Edit your config file!')
+
+def check_imports():
+    try:
+        import tweepy
+    except ImportError:
+        error_exit('Failed to import the Tweepy library! (http://pypi.python.org/pypi/tweepy)')
+
+def check_privileges():
+    if check_windows():
+        if ctypes.windll.shell32.IsUserAnAdmin() != 0:
+            return True
+        else:
+            return False
+    else:
+        if os.getuid() == 0 or os.geteuid() == 0:
+            return True
+        else:
+            return False
+
+def check_version(major):
+    if sys.version_info.major == major:
+        return True
+    else:
+        return False
+
+def check_windows():
+    if os.name == 'nt':
+        return True
+    else:
+        return False
+
+def clear():
+    if check_windows():
+        os.system('cls')
+    else:
+        os.system('clear')
+
+def error(msg, reason=None):
+    if reason:
+        print('%s | [!] - %s (%s)' % (get_time(), msg, str(reason)))
+    else:
+        print('%s | [!] - %s' % (get_time(), msg))
+
+def error_exit(msg):
+    raise SystemExit('%s | [!] - %s' % (get_time(), msg))
+
+def get_time():
+    return time.strftime('%I:%M:%S')
+
+def get_windows():
+    if os.name == 'nt':
+        return True
+    else:
+        return False
+
+def info():
+    clear()
+    print(''.rjust(56, '#'))
+    print('#{0}#'.format(''.center(54)))
+    print('#{0}#'.format('Booster Twitter Bot'.center(54)))
+    print('#{0}#'.format('Developed by acidvegas in Python 3'.center(54)))
+    print('#{0}#'.format('https://acid.vegas/booster'.center(54)))
+    print('#{0}#'.format(''.center(54)))
+    print(''.rjust(56, '#'))
+
+
+def keep_alive():
+    try:
+        while True:
+            input('')
+    except KeyboardInterrupt:
+        sys.exit()
diff --git a/booster/functions.py b/booster/functions.py
new file mode 100644
index 0000000..956cb06
--- /dev/null
+++ b/booster/functions.py
@@ -0,0 +1,23 @@
+#!/usr/bin/env python
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
+# functions.py
+
+import datetime
+import random
+import urllib.request
+
+def get_day():
+    return datetime.datetime.today().weekday()
+
+def get_source(url):
+    req = urllib.request.Request(url)
+    req.add_header('User-Agent', 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)')
+    source  = urllib.request.urlopen(req, timeout=10)
+    charset = source.headers.get_content_charset()
+    if charset:
+        return source.read().decode(charset)
+    else:
+        return source.read().decode()
+
+def random_int(min, max):
+    return random.randint(min, max)
diff --git a/booster/twitter.py b/booster/twitter.py
new file mode 100644
index 0000000..e2ba905
--- /dev/null
+++ b/booster/twitter.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env python
+# Booster Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/booster)
+# twitter.py
+
+import random
+import threading
+import time
+
+import tweepy
+
+import config
+import debug
+import functions
+
+class Booster(object):
+    def __init__(self):
+        self.api           = None
+        self.me            = None
+        self.favorites     = 0
+        self.max_favorites = config.max_favorites
+        self.follows       = 0
+        self.max_follows   = config.max_follows
+        self.messages      = 0
+        self.max_messages  = config.max_messages
+        self.tweets        = 0
+        self.max_tweets    = config.max_tweets
+        self.unfollows     = 0
+        self.max_unfollows = config.max_unfollows
+        self.send_message  = config.send_message
+        self.message       = config.message
+
+    def run(self):
+        self.login()
+        threading.Thread(target=self.loop_boost).start()
+        threading.Thread(target=self.loop_favorite).start()
+        threading.Thread(target=self.loop_follow).start()
+        threading.Thread(target=self.loop_search).start()
+#        threading.Thread(target=self.loop_trend).start()
+
+    def login(self):
+        try:
+            auth = tweepy.OAuthHandler(config.consumer_key, config.consumer_secret)
+            auth.set_access_token(config.access_token, config.access_token_secret)
+            self.api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
+            self.me  = self.api.me()
+        except tweepy.TweepError as ex:
+            debug.error_exit('Failed to login to Twitter! ({0})'.format(str(ex)))
+
+    def loop_boost(self):
+        while True:
+            try:
+                if 'boost_tweet' in locals(): self.api.destroy_status(boost_tweet.id)
+                boost_tweet = self.api.update_status('RT for followers! #' + ' #'.join(config.boost_keywords))
+                self.tweets += 1
+                debug.alert('Re-posted boost tweet.')
+            except tweepy.TweepError as ex:
+                debug.error('Error occured in the boost loop', ex)
+            finally:
+                random.shuffle(config.boost_keywords)
+                time.sleep(60*5)
+
+    def loop_favorite(self):
+        while True:
+            try:
+                for tweet in tweepy.Cursor(api.home_timeline, exclude_replies=True).items(50):
+                    if tweet.user.screen_name != me.screen_name:
+                        if not tweet.favorited:
+                            if random.choice((True, False, False, False, False)):
+                                api.create_favorite(tweet.id)
+                                self.favorites += 1
+                                debug.alert('Favorited a friends tweet!')
+                    time.sleep(30)
+            except tweepy.TweepError as ex:
+                debug.error('Error occured in the favorite loop!', ex)
+            finally:
+                time.sleep(60*15)
+
+    def loop_follow(self):
+        while True:
+            try:
+                followers   = api.followers_ids(me.screen_name)
+                friends     = api.friends_ids(me.screen_name)
+                non_friends = [friend for friend in followers if friend not in friends]
+                debug.action('Following back {0} supporters...'.format(len(non_friends)))
+                for follower in non_friends:
+                    api.create_friendship(follower)
+                    self.follows += 1
+                    debug.alert('Followed back a follower!')
+                    if self.follows >= self.max_follows:
+                        break
+                    if self.send_message:
+                        api.send_direct_message(screen_name=follower, text=self.message)
+                    time.sleep(30)
+            except tweepy.TweepError as ex:
+                debug.error('Error occured in the follow loop!', ex)
+            finally:
+                time.sleep(60*15)
+
+    def loop_search(self):
+        while True:
+            try:
+                query = random.choice(config.boost_keywords)
+                for item in api.search(q='#' + query, count=50, lang='en', result_type='recent'):
+                    if not item.user.following and not item.favorited:
+                        try:
+                            api.create_favorite(item.id)
+                            api.create_friendship(item.user.screen_name)
+                            self.favorites += 1
+                            self.follows += 1
+                            debug.alert('Followed a booster twitter!')
+                        except tweepy.TweepError as ex:
+                            debug.error('Unknown error occured in the search loop!', ex)
+                    time.sleep(30)
+            except tweepy.TweepError as ex:
+                debug.error('Error occured in the search loop!', ex)
+            finally:
+                time.sleep(60*15)
+
+    def loop_trend(self):
+        while True:
+            try:
+                trends    = self.api.trends_place(str(config.woeid))
+                hashtags = [x['name'] for x in trends[0]['trends'] if x['name'].startswith('#')]
+                for trend in hashtags:
+                    for item in self.api.search(q=trend, count=5, lang='en', result_type='top'):
+                        #self.api.update_status(item.tweet) # FIX THIS PART
+                        time.sleep(30)
+            except tweepy.TweepError as ex:
+                debug.error('Error occured in the trend loop!', ex)
+            finally:
+                time.sleep(60*15)
+
+    def loop_unfollow(self):
+        try:
+            followers   = self.api.followers_ids(self.me.screen_name)
+            friends     = self.api.friends_ids(self.me.screen_name)
+            non_friends = [friend for friend in friends if friend not in followers]
+            non_friends.reverse()
+            debug.action('Unfollowing {0} unsupporting friends...'.format(len(non_friends)))
+            for friend in non_friends:
+                self.api.destroy_friendship(friend)
+                self.unfollows += 1
+                debug.alert('Unfollowed an unsupporting friend!')
+                if self.unfollows == self.max_unfollows:
+                    break
+                else:
+                    time.sleep(60*functions.random_int(10,15))
+        except tweepy.TweepError as ex:
+            debug.error('Error occured in the unfollow loop!', ex)
+        finally:
+            self.unfollows = 0
+
+    def ratio_check(self):
+        if self.follows >= max_follows:
+            time.sleep(86400)
+        if me.friends_count >= 2000:
+            ratio = me.friends_count + (me.followers_count/10)
+            if me.friends_count >= ratio:
+                debug.action('Following to follower ratio is off! Starting the unfollow loop...')
+                unfollow_loop()
+
+    def stats(self):
+        debug.action('SceenName  : ' + self.me.screen_name)
+        debug.action('Registered : ' + self.me.created_at)
+        debug.action('Favorites  : ' + self.me.favourites_count)
+        debug.action('Following  : ' + self.me.friends_count)
+        debug.action('Followers  : ' + self.me.followers_count)
+        debug.action('Tweets     : ' + self.me.statuses_count)