Skip to content

Commit

Permalink
Merge pull request #47 from GoldenChrysus/master
Browse files Browse the repository at this point in the history
Update altcointip for newer dependencies and general bug fixes
  • Loading branch information
vindimy committed Jan 31, 2018
2 parents b295379 + 504a9fb commit 83c9fac
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 105 deletions.
6 changes: 3 additions & 3 deletions src/_start.sh
Expand Up @@ -2,7 +2,7 @@

user=$1

if [ ! -f ./cointipbot.py ] ; then
if [ ! -f ./main.py ] ; then
# Output help message and exit
echo "Usage: $0 [username]"
echo "if [username] is specified, script will be started as user [username]"
Expand All @@ -12,8 +12,8 @@ fi

if [ -z "$user" ] ; then
# Run as current user
python -c 'import cointipbot; cb=cointipbot.CointipBot(); cb.main()'
python -c 'import main; main=main.Main(); main.main()'
else
# Run as $user
sudo su - $user -c "cd `pwd` && python -c 'import cointipbot; cb=cointipbot.CointipBot(); cb.main()'"
sudo su - $user -c "cd `pwd` && python -c 'import main; main=main.Main(); main.main()'"
fi
112 changes: 55 additions & 57 deletions src/cointipbot.py
Expand Up @@ -23,14 +23,13 @@
from jinja2 import Environment, PackageLoader

from requests.exceptions import HTTPError, ConnectionError, Timeout
from praw.errors import ExceptionList, APIException, InvalidCaptcha, InvalidUser, RateLimitExceeded
from praw.exceptions import APIException, ClientException
from socket import timeout

# Configure CointipBot logger
logging.basicConfig()
lg = logging.getLogger('cointipbot')


class CointipBot(object):
"""
Main class for cointip bot
Expand Down Expand Up @@ -87,7 +86,11 @@ def parse_config(self):
prefix='./conf/'
for i in ['coins', 'db', 'exchanges', 'fiat', 'keywords', 'logs', 'misc', 'reddit', 'regex']:
lg.debug("CointipBot::parse_config(): reading %s%s.yml", prefix, i)
conf[i] = yaml.load(open(prefix+i+'.yml'))

file = open(prefix + i + '.yml')
conf[i] = yaml.load(file)

file.close()
except yaml.YAMLError as e:
lg.error("CointipBot::parse_config(): error reading config file: %s", e)
if hasattr(e, 'problem_mark'):
Expand Down Expand Up @@ -121,8 +124,13 @@ def connect_reddit(self):
"""
lg.debug('CointipBot::connect_reddit(): connecting to Reddit...')

conn = praw.Reddit(user_agent = self.conf.reddit.auth.user)
conn.login(self.conf.reddit.auth.user, self.conf.reddit.auth.password)
conn = praw.Reddit(
user_agent = self.conf.reddit.auth.user,
client_id = self.conf.reddit.auth.client_id,
client_secret = self.conf.reddit.auth.client_secret,
username = self.conf.reddit.auth.user,
password = self.conf.reddit.auth.password
)

lg.info("CointipBot::connect_reddit(): logged in to Reddit as %s", self.conf.reddit.auth.user)
return conn
Expand Down Expand Up @@ -192,29 +200,29 @@ def check_inbox(self):
try:

# Try to fetch some messages
messages = list(ctb_misc.praw_call(self.reddit.get_unread, limit=self.conf.reddit.scan.batch_limit))
messages = list(ctb_misc.praw_call(self.reddit.inbox.unread, limit=self.conf.reddit.scan.batch_limit))
messages.reverse()

# Process messages
for m in messages:
# Sometimes messages don't have an author (such as 'you are banned from' message)
if not m.author:
lg.info("CointipBot::check_inbox(): ignoring msg with no author")
ctb_misc.praw_call(m.mark_as_read)
ctb_misc.praw_call(m.mark_read)
continue

lg.info("CointipBot::check_inbox(): %s from %s", "comment" if m.was_comment else "message", m.author.name)

# Ignore duplicate messages (sometimes Reddit fails to mark messages as read)
if ctb_action.check_action(msg_id=m.id, ctb=self):
lg.warning("CointipBot::check_inbox(): duplicate action detected (msg.id %s), ignoring", m.id)
ctb_misc.praw_call(m.mark_as_read)
ctb_misc.praw_call(m.mark_read)
continue

# Ignore self messages
if m.author and m.author.name.lower() == self.conf.reddit.auth.user.lower():
lg.debug("CointipBot::check_inbox(): ignoring message from self")
ctb_misc.praw_call(m.mark_as_read)
ctb_misc.praw_call(m.mark_read)
continue

# Ignore messages from banned users
Expand All @@ -223,7 +231,7 @@ def check_inbox(self):
u = ctb_user.CtbUser(name = m.author.name, redditobj = m.author, ctb = self)
if u.banned:
lg.info("CointipBot::check_inbox(): ignoring banned user '%s'" % m.author)
ctb_misc.praw_call(m.mark_as_read)
ctb_misc.praw_call(m.mark_read)
continue

action = None
Expand All @@ -249,17 +257,12 @@ def check_inbox(self):
user.tell(subj='What?', msg=msg, msgobj=m if not m.was_comment else None)

# Mark message as read
ctb_misc.praw_call(m.mark_as_read)
ctb_misc.praw_call(m.mark_read)

except (HTTPError, ConnectionError, Timeout, timeout) as e:
lg.warning("CointipBot::check_inbox(): Reddit is down (%s), sleeping", e)
time.sleep(self.conf.misc.times.sleep_seconds)
pass
except RateLimitExceeded as e:
lg.warning("CointipBot::check_inbox(): rate limit exceeded, sleeping for %s seconds", e.sleep_time)
time.sleep(e.sleep_time)
time.sleep(1)
pass
except Exception as e:
lg.error("CointipBot::check_inbox(): %s", e)
raise
Expand All @@ -285,7 +288,7 @@ def init_subreddits(self):

elif self.conf.reddit.scan.my_subreddits:
# Subreddits are subscribed to by bot user
my_reddits = ctb_misc.praw_call(self.reddit.get_my_subreddits, limit=None)
my_reddits = ctb_misc.praw_call(self.reddit.user.subreddits, limit=None)
my_reddits_list = []
for my_reddit in my_reddits:
my_reddits_list.append(my_reddit.display_name.lower())
Expand All @@ -301,7 +304,7 @@ def init_subreddits(self):

# Get multi-reddit PRAW object
lg.debug("CointipBot::check_subreddits(): multi-reddit string: %s", my_reddits_string)
self.conf.reddit.subreddits = ctb_misc.praw_call(self.reddit.get_subreddit, my_reddits_string)
self.conf.reddit.subreddits = ctb_misc.praw_call(self.reddit.subreddit, my_reddits_string)

except Exception as e:
lg.error("CointipBot::check_subreddits(): coudln't get subreddits: %s", e)
Expand Down Expand Up @@ -367,7 +370,7 @@ def check_subreddits(self):
if counter >= self.conf.reddit.scan.batch_limit - 1:
lg.warning("CointipBot::check_subreddits(): conf.reddit.scan.batch_limit (%s) was not large enough to process all comments", self.conf.reddit.scan.batch_limit)

except (HTTPError, RateLimitExceeded, timeout) as e:
except (HTTPError, timeout) as e:
lg.warning("CointipBot::check_subreddits(): Reddit is down (%s), sleeping", e)
time.sleep(self.conf.misc.times.sleep_seconds)
pass
Expand All @@ -394,6 +397,32 @@ def refresh_ev(self):
lg.debug("< CointipBot::refresh_ev(): DONE (skipping)")
return

# For each enabled fiat...
for f in vars(self.conf.fiat):
if self.conf.fiat[f].enabled:

# Get fiat/BTC exchange rate
values = []
result = 0.0

# For each exchange that supports this fiat...
for e in self.exchanges:
if self.exchanges[e].supports_pair(_name1='btc', _name2=self.conf.fiat[f].unit):
# Get ticker value from exchange
value = self.exchanges[e].get_ticker_value(_name1='btc', _longname1='bitcoin', _name2=self.conf.fiat[f].unit)
if value and float(value) > 0.0:
values.append(float(value))

# Result is average of all responses
if len(values) > 0:
result = sum(values) / float(len(values))

# Assign result to self.runtime['ev']
if not self.runtime['ev'].has_key('btc'):
self.runtime['ev']['btc'] = {}

self.runtime['ev']['btc'][f] = result

# For each enabled coin...
for c in vars(self.conf.coins):
if self.conf.coins[c].enabled:
Expand All @@ -407,7 +436,7 @@ def refresh_ev(self):
for e in self.exchanges:
if self.exchanges[e].supports_pair(_name1=self.conf.coins[c].unit, _name2='btc'):
# Get ticker value from exchange
value = self.exchanges[e].get_ticker_value(_name1=self.conf.coins[c].unit, _name2='btc')
value = self.exchanges[e].get_ticker_value(_name1=self.conf.coins[c].unit, _longname1=self.conf.coins[c].name.lower(), _name2='btc')
if value and float(value) > 0.0:
values.append(float(value))

Expand All @@ -422,32 +451,13 @@ def refresh_ev(self):
# Assign result to self.runtime['ev']
if not self.runtime['ev'].has_key(c):
self.runtime['ev'][c] = {}
self.runtime['ev'][c]['btc'] = result

# For each enabled fiat...
for f in vars(self.conf.fiat):
if self.conf.fiat[f].enabled:

# Get fiat/BTC exchange rate
values = []
result = 0.0

# For each exchange that supports this fiat...
for e in self.exchanges:
if self.exchanges[e].supports_pair(_name1='btc', _name2=self.conf.fiat[f].unit):
# Get ticker value from exchange
value = self.exchanges[e].get_ticker_value(_name1='btc', _name2=self.conf.fiat[f].unit)
if value and float(value) > 0.0:
values.append(float(value))

# Result is average of all responses
if len(values) > 0:
result = sum(values) / float(len(values))
self.runtime['ev'][c]['btc'] = result

# Assign result to self.runtime['ev']
if not self.runtime['ev'].has_key('btc'):
self.runtime['ev']['btc'] = {}
self.runtime['ev']['btc'][f] = result
# For each enabled fiat...
for f in vars(self.conf.fiat):
if self.conf.fiat[f].enabled:
self.runtime['ev'][c][f] = self.runtime['ev']['btc'][f] * self.runtime['ev'][c]['btc']

lg.debug("CointipBot::refresh_ev(): %s", self.runtime['ev'])

Expand Down Expand Up @@ -573,16 +583,4 @@ def main(self):
# Send a notification, if enabled
if self.conf.misc.notify.enabled:
self.notify(_msg=tb)
sys.exit(1)

def secondary():
try:
while True:
main(self)
except:
traceback.print_exc()
print('Resuming in 30sec...')
time.sleep(30)
print('Resumed')
while True:
secondary()
sys.exit(1)
10 changes: 5 additions & 5 deletions src/conf-sample/db.yml
Expand Up @@ -11,17 +11,17 @@ sql:
name: "Total Accepted Tips (USD)"
desc: "Total value of all tips given and accepted in USD (default) fiat"
type: line
query: "SELECT SUM(fiat_val) AS total_usd, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat = 'usd'"
query: "SELECT SUM(fiat_val) AS total_usd, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat = 'usd' GROUP BY fiat"
01a_total_tipped_usd_by_coin:
name: "Total Accepted Tips (USD) By Coin"
desc: "Total value of all tips given and accepted in USD (default) fiat grouped by coin"
type: table
query: "SELECT coin, SUM(fiat_val) AS total_usd, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat = 'usd' GROUP BY coin ORDER BY coin"
query: "SELECT coin, SUM(fiat_val) AS total_usd, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat = 'usd' GROUP BY coin, fiat ORDER BY coin"
02_total_tips_expired_and_declined:
name: "Total Expired and Declined Tips (USD)"
desc: "Total value of all tips given that weren't accepted (expired or declined) in USD (default) fiat"
type: line
query: "SELECT SUM(fiat_val) AS total_usd, fiat FROM t_action WHERE type = 'givetip' AND state = 'expired' OR state = 'declined' AND fiat = 'usd'"
query: "SELECT SUM(fiat_val) AS total_usd, fiat FROM t_action WHERE type = 'givetip' AND (state = 'expired' OR state = 'declined') AND fiat = 'usd' GROUP BY fiat"
03_total_users_registered:
name: "Total Users Registered"
desc: "Number of registered users"
Expand Down Expand Up @@ -51,7 +51,7 @@ sql:
name: "Top 10 Tippers"
desc: "Top 10 all-time tippers as determined by total USD/EUR (fiat) value of their tips."
type: table
query: "SELECT from_user, SUM(fiat_val) AS total_fiat, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat IN ('usd', 'eur') GROUP BY from_user ORDER BY total_fiat DESC LIMIT 10"
query: "SELECT from_user, SUM(fiat_val) AS total_fiat, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat IN ('usd', 'eur') GROUP BY from_user, fiat ORDER BY total_fiat DESC LIMIT 10"
07_top_10_tips:
name: "Top 10 Tips"
desc: "Top 10 all-time tips as determined by their USD/EUR (fiat) value."
Expand Down Expand Up @@ -91,7 +91,7 @@ sql:
name: "Top 10 Receivers"
desc: "Top 10 all-time tip receivers as determined by total USD/EUR (fiat) value of their received tips."
type: table
query: "SELECT to_user, SUM(fiat_val) AS total_fiat, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat IN ('usd', 'eur') AND to_user IS NOT NULL GROUP BY to_user ORDER BY total_fiat DESC LIMIT 10"
query: "SELECT to_user, SUM(fiat_val) AS total_fiat, fiat FROM t_action WHERE type = 'givetip' AND state = 'completed' AND fiat IN ('usd', 'eur') AND to_user IS NOT NULL GROUP BY to_user, fiat ORDER BY total_fiat DESC LIMIT 10"
userstats:
users: "SELECT username FROM t_users WHERE username IN (SELECT from_user FROM t_action WHERE type = 'givetip') OR username in (SELECT to_user FROM t_action WHERE type = 'givetip') ORDER BY username"
coins: 'SELECT DISTINCT coin FROM t_action WHERE coin IS NOT NULL ORDER BY coin'
Expand Down
22 changes: 22 additions & 0 deletions src/conf-sample/exchanges.yml
Expand Up @@ -7,6 +7,7 @@ blockchaininfo:
coinlist: ['btc']
fiatlist: ['usd','cny','jpy','sgd','hkd','cad','aud','nzd','gbp','dkk','sek','brl','chf','eur','rub','sll','pln','thb']
uppercase: true
longname: false

vircurex:
enabled: true
Expand All @@ -17,6 +18,7 @@ vircurex:
coinlist: ['anc','btc','dgc','dvc','frc','ftc','i0c','ixc','ltc','nmc','nvc','ppc','trc','xpm']
fiatlist: ['usd','eur']
uppercase: true
longname: false

btce:
enabled: true
Expand All @@ -27,6 +29,7 @@ btce:
coinlist: ['btc','ltc','nmc','nvc','trc','ppc','ftc','xpm']
fiatlist: ['usd','eur','rur']
uppercase: false
longname: false

bitstamp:
enabled: true
Expand All @@ -37,6 +40,7 @@ bitstamp:
coinlist: ['btc']
fiatlist: ['usd']
uppercase: false
longname: false

mtgox:
enabled: false
Expand All @@ -47,6 +51,7 @@ mtgox:
coinlist: ['btc']
fiatlist: ['usd','eur','jpy','gbp','rub']
uppercase: true
longname: false

campbx:
enabled: true
Expand All @@ -57,6 +62,7 @@ campbx:
coinlist: ['btc']
fiatlist: ['usd']
uppercase: false
longname: false

cryptsy:
enabled: true
Expand All @@ -67,6 +73,7 @@ cryptsy:
coinlist: ['btc','alf','amc','anc','arg','bqc','bte','btg','buk','cap','cgb','clr','cmc','crc','csc','dgc','dmd','elc','emd','frc','frk','fst','ftc','gdc','glc','glx','hbn','ixc','kgc','lk7','lky','ltc','mec','mnc','nbl','nec','nmc','nrb','nvc','phs','ppc','pts','pxc','pyc','qrk','sbc','spt','src','tag','tek','trc','wdc','xjo','xpm','yac','zet']
fiatlist: []
uppercase: true
longname: false

bter:
enabled: true
Expand All @@ -77,6 +84,7 @@ bter:
coinlist: ['btc','ltc','ppc','frc','ftc','cnc','bqc','btb','wdc','yac','xpm','pts','zcc','dtc','red','cent','zet','src','mec','qrk']
fiatlist: ['cny']
uppercase: false
longname: false

cryptotrade:
enabled: true
Expand All @@ -87,6 +95,7 @@ cryptotrade:
coinlist: ['btc','ltc','nmc','xpm','ppc','trc','ftc','dvc','wdc','dgc']
fiatlist: ['usd','eur']
uppercase: false
longname: false

coinse:
enabled: true
Expand All @@ -97,6 +106,7 @@ coinse:
coinlist: ['btc','alp','amc','anc','bet','bqc','cgb','cin','crc','dem','dtc','elc','elp','emd','frk','ftc','gdc','glc','kgc','ltc','mec','nan','net','nrb','nvc','orb','ppc','pts','qrk','rec','red','spt','tag','trc','uno','wdc','xnc','xpm','zet']
fiatlist: []
uppercase: true
longname: false

cryptocoincharts:
enabled: true
Expand All @@ -107,3 +117,15 @@ cryptocoincharts:
coinlist: ['btc','ltc','ppc','nmc','xmp','mec','bqc','dgc','ifc','ixc','mnc','qrk','sbc','zet','doge','nxt','msc','ftc','nvc','dvc','frc','trc']
fiatlist: ['usd','eur']
uppercase: false
longname: false

coinmarketcap:
enabled: true
domain: 'api.coinmarketcap.com'
https: true
urlpaths: ['/v1/ticker/{THING_FROM}/?convert={THING_TO}']
jsonpaths: ['0.price_{THING_TO}']
coinlist: ['dgb','btc']
fiatlist: ['usd','eur']
uppercase: false
longname: true
2 changes: 2 additions & 0 deletions src/conf-sample/reddit.yml
@@ -1,6 +1,8 @@
auth:
user: 'mybotuser'
password: 'mybotpass'
client_id: 'abcdefg'
client_secret: 'supersecretsecret'

scan:
batch_limit: 1000
Expand Down

0 comments on commit 83c9fac

Please sign in to comment.