mirror of
git://git.acid.vegas/chir.py.git
synced 2024-12-28 01:16:37 +00:00
Initial commit
This commit is contained in:
commit
010429dae4
15
LICENSE
Normal file
15
LICENSE
Normal file
@ -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.
|
24
README.md
Normal file
24
README.md
Normal file
@ -0,0 +1,24 @@
|
||||
###### Requirments
|
||||
* [FeedParser](http://pypi.python.org/pypi/feedparser)
|
||||
* [Tweepy](http://pypi.python.org/pypi/tweepy)
|
||||
* [ndg-httpsclient](http://pypi.python.org/pypi/ndg-httpsclient) *(Install only if you are getting an "InsecurePlatformWarning" error.)*
|
||||
|
||||
###### 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".
|
||||
|
||||
Register a [CoinURL](http://coinurl.com/) account and get your [api key](http://coinurl.com/profile-api.php).
|
||||
The random number you will see after "uuid" is your unique user id that will be use in the config.
|
||||
|
||||
Edit your `config.py` and change the Twitter & CoinURL API settings.
|
||||
|
||||
###### Mirrors
|
||||
- [acid.vegas](https://acid.vegas/chir.py) *(main)*
|
||||
- [SuperNETs](https://git.supernets.org/acidvegas/chir.py)
|
||||
- [GitHub](https://github.com/acidvegas/chir.py)
|
||||
- [GitLab](https://gitlab.com/acidvegas/chir.py)
|
22
chir.py/chir.py
Normal file
22
chir.py/chir.py
Normal file
@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python
|
||||
# Chir.py Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/chir.py)
|
||||
# chir.py
|
||||
|
||||
import sys
|
||||
|
||||
sys.dont_write_bytecode = True
|
||||
|
||||
import debug
|
||||
|
||||
debug.info()
|
||||
if not debug.check_version(3):
|
||||
debug.error_exit('Chir.py requires Python version 3 to run!')
|
||||
if not debug.get_windows():
|
||||
if debug.check_root():
|
||||
debug.error_exit('Do not run Chir.py as root!')
|
||||
debug.check_imports()
|
||||
debug.check_config()
|
||||
import twitter
|
||||
twitter.login()
|
||||
twitter.main_loop()
|
||||
debug.keep_alive()
|
39
chir.py/config.py
Normal file
39
chir.py/config.py
Normal file
@ -0,0 +1,39 @@
|
||||
#!/usr/bin/env python
|
||||
# Chir.py Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/chir.py)
|
||||
# config.py
|
||||
|
||||
# API Settings
|
||||
coinurl_uuid = 'CHANGEME'
|
||||
twitter_consumer_key = 'CHANGEME'
|
||||
twitter_consumer_secret = 'CHANGEME'
|
||||
twitter_access_token = 'CHANGEME'
|
||||
twitter_access_token_secret = 'CHANGEME'
|
||||
|
||||
# Keywords & News Sources (DO NOT EDIT)
|
||||
boost_keywords = ('500aday','autofollow','autofollowback','f4f','follow','follow4follow','followback','followtrain','teamfollowback','wefollowback')
|
||||
|
||||
news_feeds = {
|
||||
'baseball' : 'https://sports.yahoo.com/mlb/rss.xml',
|
||||
'basketball' : 'https://sports.yahoo.com/nba/rss.xml',
|
||||
'boxing' : 'https://sports.yahoo.com/box/rss.xml',
|
||||
'football' : 'https://sports.yahoo.com/nfl/rss.xml',
|
||||
'golf' : 'https://sports.yahoo.com/golf/rss.xml',
|
||||
'hockey' : 'https://sports.yahoo.com/nhl/rss.xml',
|
||||
'mma' : 'https://sports.yahoo.com/mma/rss.xml',
|
||||
'nascar' : 'https://sports.yahoo.com/nascar/rss.xml',
|
||||
'soccer' : 'https://sports.yahoo.com/soccer/rss.xml',
|
||||
'tennis' : 'https://sports.yahoo.com/tennis/rss.xml'
|
||||
}
|
||||
|
||||
news_keywords = {
|
||||
'baseball' : ('baseball','mlb','homerun','worldseries','springtraining','angels','astros','athletics','bluejays','braves','brewers','cardinals','cubs','diamondbacks','dodgers','giants','indians','mariners','marlins','mets','nationals','orioles','padres','phillies','pirates','rangers','rays','redsox','reds','rockies','royals','tigers','twins','whitesox','yankees'),
|
||||
'basketball' : ('basketball','finals','nba','76ers','blazers','bucks','bulls','cavaliers','celtics','clippers','grizzlies','hawks','heat','hornets','jazz','kings','knicks','lakers','magic','mavericks','nets','nuggets','pacers','pistons','raptors','rockets','spurs','suns','thunder','timberwolves','warriors','wizards'),
|
||||
'boxing' : ('boxing','fightnight'),
|
||||
'football' : ('football','madden','nfl','superbowl','touchdown','49ers','bears','bengals','bills','broncos','browns','bucaneers','cardinals','chargers','cheifs','colts','cowboys','dolphins','eagles','falcons','giants','jaguars','jets','lions','packers','panthers','patriots','raiders','rams','ravens','redskins','saints','seahawks','steelers','texans','titans','vikings'),
|
||||
'golf' : ('fedexcup','owgr','pga','pgachampionship','pgatour'),
|
||||
'hockey' : ('hockey','nhl','worldcup','avalanche','blackhawks','bluejackets','blues','bruins','canadiens','canucks','capitals','coyotes','devils','ducks','flames','flyers','hurricanes','islanders','jets','kings','lightning','mapleleafs','oilers','panthers','penguins','predators','rangers','redwings','sabres','senators','sharks','stars','wild'),
|
||||
'mma' : ('bellator','martialarts','mixedmartialarts','mma','ufc','wsof'),
|
||||
'nascar' : ('buschseries','campingworldtruckseries','daytona500','iracing','nascar','sprintcup','sprintseries','winstoncup','winstoncupseries','xfinityseries'),
|
||||
'soccer' : ('fifa','soccer','worldcup'),
|
||||
'tennis' : ('atp','atpworldtour','masters1000','tennis','usopen')
|
||||
}
|
89
chir.py/debug.py
Normal file
89
chir.py/debug.py
Normal file
@ -0,0 +1,89 @@
|
||||
#!/usr/bin/env python
|
||||
# Chir.py Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/chir.py)
|
||||
# debug.py
|
||||
|
||||
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.coinurl_uuid, config.twitter_consumer_key, config.twitter_consumer_secret, config.twitter_access_token, config.twitter_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)')
|
||||
try:
|
||||
import feedparser
|
||||
except ImportError:
|
||||
error_exit('Failed to import the FeedParser library! (http://pypi.python.org/pypi/feedparser)')
|
||||
|
||||
def check_root():
|
||||
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('#' + ''.center(54) + '#')
|
||||
print('#' + 'Chir.py Twitter Bot'.center(54) + '#')
|
||||
print('#' + 'Developed by acidvegas in Python '.center(54) + '#')
|
||||
print('#' + 'https://acid.vegas/chir.py'.center(54) + '#')
|
||||
print('#' + ''.center(54) + '#')
|
||||
print(''.rjust(56, '#'))
|
||||
|
||||
def keep_alive():
|
||||
try:
|
||||
while True:
|
||||
input('')
|
||||
except KeyboardInterrupt:
|
||||
sys.exit()
|
55
chir.py/functions.py
Normal file
55
chir.py/functions.py
Normal file
@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
# Chir.py Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/chir.py)
|
||||
# functions.py
|
||||
|
||||
import random
|
||||
import re
|
||||
import urllib.request
|
||||
|
||||
import feedparser
|
||||
|
||||
import config
|
||||
import debug
|
||||
|
||||
def coinurl(url):
|
||||
source = urllib.request.urlopen('https://coinurl.com/api.php?uuid=%s&url=%s' % (config.coinurl_uuid, url))
|
||||
charset = source.headers.get_content_charset()
|
||||
if charset : return source.read().decode(charset)
|
||||
else : return source.read().decode()
|
||||
|
||||
def get_news(): # This is very sloppy and needs some work.
|
||||
news_list = list()
|
||||
sport = random.choice(list(config.news_feeds.keys()))
|
||||
sport_news = feedparser.parse(config.news_feeds[sport])
|
||||
sport_keywords = config.news_keywords[sport]
|
||||
for item in sport_news.entries:
|
||||
description = strip_html(item.summary)
|
||||
if ') -- ' in description:
|
||||
cutoff = description.split(') -- ')[0]
|
||||
description = description.split(cutoff)[1]
|
||||
if ') - ' in description:
|
||||
cutoff = description.split(') - ')[0]
|
||||
description = description.split(cutoff)[1]
|
||||
description = description.replace('*', '')
|
||||
description = description.replace('\'', '')
|
||||
description = description.replace('"', '')
|
||||
description = description.replace('--', '-')
|
||||
description = description.replace(' ', ' ')
|
||||
for word in sport_keywords:
|
||||
if word in description.lower():
|
||||
description = re.sub(word, '#' + word, description, flags=re.IGNORECASE)
|
||||
if len(description) > 118:
|
||||
description = description[:118]
|
||||
split = description.split()
|
||||
description = description.split(split[len(split)-1])[0][:-1] + '... '
|
||||
try:
|
||||
link = coinurl(item.link)
|
||||
except Exception as ex:
|
||||
debug.error('Error occured creating PPC link!', ex)
|
||||
else:
|
||||
description = description + ' ' + link
|
||||
news_list.append(description)
|
||||
return news_list
|
||||
|
||||
def strip_html(source):
|
||||
return re.compile(r'<.*?>').sub('', source)
|
155
chir.py/twitter.py
Normal file
155
chir.py/twitter.py
Normal file
@ -0,0 +1,155 @@
|
||||
#!/usr/bin/env python
|
||||
# Chir.py Twitter Bot - Developed by acidvegas in Python (https://acid.vegas/chir.py)
|
||||
# twitter.py
|
||||
|
||||
import random
|
||||
import threading
|
||||
import time
|
||||
|
||||
import tweepy
|
||||
|
||||
import config
|
||||
import debug
|
||||
import functions
|
||||
|
||||
api = None
|
||||
me = None
|
||||
|
||||
def login():
|
||||
global api, me
|
||||
try:
|
||||
auth = tweepy.OAuthHandler(config.consumer_key, config.consumer_secret)
|
||||
auth.set_access_token(config.access_token, config.access_token_secret)
|
||||
api = tweepy.API(auth, wait_on_rate_limit=True, wait_on_rate_limit_notify=True)
|
||||
me = api.me()
|
||||
except tweepy.TweepError:
|
||||
debug.error_exit('Failed to login to Twitter!')
|
||||
|
||||
def stats():
|
||||
debug.action('SceenName\t: %s' % me.screen_name)
|
||||
debug.action('Registered\t: %s' % me.created_at)
|
||||
debug.action('Favorites\t: %s' % me.favourites_count)
|
||||
debug.action('Following\t: %s' % me.friends_count)
|
||||
debug.action('Followers\t: %s' % me.followers_count)
|
||||
debug.action('Tweets\t\t: %s' % me.statuses_count)
|
||||
|
||||
class boost_loop(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
def run(self):
|
||||
while True:
|
||||
try:
|
||||
if 'boost_tweet' in locals(): api.destroy_status(boost_tweet.id)
|
||||
boost_tweet = api.update_status('Support our Twitter! #' + ' #'.join(config.boost))
|
||||
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)
|
||||
time.sleep(60*5)
|
||||
|
||||
class favorite_loop(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
def run(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)
|
||||
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)
|
||||
|
||||
class follow_loop(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
def run(self):
|
||||
while True:
|
||||
try:
|
||||
followers = api.followers_ids(me.screen_name)
|
||||
friends = api.friends_ids(me.screen_name)
|
||||
if me.friends_count / me.followers_count == 3:
|
||||
debug.action('Following to follower ratio is off! Starting the unfollow loop...')
|
||||
unfollow_loop()
|
||||
for follower in followers:
|
||||
if not follower in friends:
|
||||
api.create_friendship(follower)
|
||||
api.send_direct_message(screen_name=follower, text='Thanks for following our Twitter. Be sure to share us with your friends & keep up with the latest sports news!')
|
||||
debug.alert('Followed back a follower!')
|
||||
time.sleep(30)
|
||||
except tweepy.TweepError as ex:
|
||||
debug.error('Error occured in the follow loop!', ex)
|
||||
finally:
|
||||
time.sleep(60*15)
|
||||
|
||||
def main_loop():
|
||||
boost_loop().start()
|
||||
favorite_loop().start()
|
||||
follow_loop().start()
|
||||
news_loop().start()
|
||||
search_loop().start()
|
||||
|
||||
class news_loop(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
def run(self):
|
||||
while True:
|
||||
try:
|
||||
news = functions.get_news()
|
||||
tweets = list()
|
||||
for item in tweepy.Cursor(api.user_timeline, exclude_replies=True).items(50):
|
||||
tweets.append(item.text.split('... ')[0])
|
||||
time.sleep(2)
|
||||
for item in news:
|
||||
split = item.split('... ')[0]
|
||||
if split not in tweets:
|
||||
api.update_status(item)
|
||||
debug.alert('A tweet has been posted.')
|
||||
time.sleep(60*5)
|
||||
except tweepy.TweepError as ex:
|
||||
debug.error('Error occured in the news loop', ex)
|
||||
finally:
|
||||
time.sleep(60*15)
|
||||
|
||||
class search_loop(threading.Thread):
|
||||
def __init__(self):
|
||||
threading.Thread.__init__(self)
|
||||
def run(self):
|
||||
query_keywords = list()
|
||||
for item in config.news_keywords:
|
||||
query_keywords = query_keywords + list(config.news_keywords[item])
|
||||
query_keywords = query_keywords + config.boost_keywords
|
||||
while True:
|
||||
try:
|
||||
query = random.choice(query_keywords)
|
||||
for item in api.search(q='#' + query, count=50, lang='en', result_type='mixed'):
|
||||
if not item.user.following and not item.favorited:
|
||||
try:
|
||||
api.create_favorite(item.id)
|
||||
api.create_friendship(item.user.screen_name)
|
||||
debug.alert('Followed a similar 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 unfollow_loop():
|
||||
try:
|
||||
followers = api.followers_ids(me.screen_name)
|
||||
friends = api.friends_ids(me.screen_name)
|
||||
for friend in friends:
|
||||
if friend not in followers:
|
||||
api.destroy_friendship(friend)
|
||||
debug.alert('Unfollowed an unsupporting friend!')
|
||||
time.sleep(30)
|
||||
except tweepy.TweepError as ex:
|
||||
debug.error('Error occured in the unfollow loop!', ex)
|
Loading…
Reference in New Issue
Block a user