commit 624276b81844714a8fde292489b879b4aa7da91b Author: acidvegas 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 + +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)