From b07bb7ba6b9e4cb6627e1c0a0ccd8985b0a96b58 Mon Sep 17 00:00:00 2001 From: moneromooo Date: Sat, 31 Jan 2015 23:40:13 +0000 Subject: [PATCH] Balances now belong to accounts, and identities map to an account --- tipbot.py | 19 +++++++----- tipbot/betutils.py | 26 ++++++++++------- tipbot/link.py | 6 ++++ tipbot/modules/bookie.py | 9 ++++-- tipbot/modules/payment.py | 9 ++++-- tipbot/modules/tipping.py | 60 +++++++++++++++++++++++--------------- tipbot/modules/withdraw.py | 5 ++-- tipbot/utils.py | 23 +++++++++++++-- 8 files changed, 107 insertions(+), 50 deletions(-) diff --git a/tipbot.py b/tipbot.py index 81b04f2..4333da5 100644 --- a/tipbot.py +++ b/tipbot.py @@ -148,9 +148,10 @@ def AddBalance(link,cmd): aidentity=Link(network,User(network,anick)).identity() else: aidentity=anick + account = GetAccount(aidentity) log_info("AddBalance: Adding %s to %s's balance" % (AmountToString(units),aidentity)) try: - balance = redis_hincrby("balances",aidentity,units) + balance = redis_hincrby("balances",account,units) except Exception, e: log_error('AddBalance: exception: %s' % str(e)) link.send( "An error has occured") @@ -349,12 +350,6 @@ def lower_nick(s,net): return news def MigrateRedis(): - balances=redis_hgetall('balances') - for balance in balances: - if balance.find(':') == -1: - redis_hset('balances','freenode:'+balance,balances[balance]) - redis_hdel('balances',balance) - keys=redisdb.keys('*') for key in keys: if key.startswith('dice:stats:') and key.find('freenode:') == -1: @@ -424,6 +419,16 @@ def MigrateRedis(): redisdb.hset(hashname,altkey,redis_hget(hashname,k)) redisdb.hdel(hashname,k) + if not redis_exists('accounts'): + idx=0 + balances = redis_hgetall('balances') + for key in balances: + redis_hset('balances',idx,balances[key]) + redis_hset('accounts',key,idx) + redis_hdel('balances',key) + idx += 1 + redis_set('next_account_id',idx) + RegisterCommands() redisdb = connect_to_redis(config.redis_host,config.redis_port) MigrateRedis() diff --git a/tipbot/betutils.py b/tipbot/betutils.py index 49dd432..8c297c3 100644 --- a/tipbot/betutils.py +++ b/tipbot/betutils.py @@ -69,12 +69,13 @@ def IsBetValid(link,amount,minbet,maxbet,potential_loss,max_loss,max_loss_ratio) def IsPlayerBalanceAtLeast(link,units): try: - balance = redis_hget("balances",link.identity()) + account = GetAccount(link) + balance = redis_hget("balances",account) if balance == None: balance = 0 balance=long(balance) if units > balance: - log_info ('%s does not have enough balance' % link.user.nick) + log_info ('%s does not have enough balance' % link.identity()) return False, "You only have %s" % (AmountToString(balance)) except Exception,e: log_error ('failed to query balance') @@ -139,6 +140,7 @@ def GetServerSeedHash(link,game): def RecordGameResult(link,game,win,lose,units): identity=link.identity() + account=GetAccount(identity) try: ts=datetime.datetime.utcnow() tsh="%u" % (ts.hour) @@ -169,7 +171,7 @@ def RecordGameResult(link,game,win,lose,units): p.zincrby(nzhtname+"wagered",tsh,units) p.zincrby(nzdtname+"wagered",tsd,units) if win: - p.hincrby("balances",identity,units) + p.hincrby("balances",account,units) p.hincrby(tname,"won",units) p.hincrby(rtname,"won",units) p.hincrby(alltname,"won",units) @@ -187,7 +189,7 @@ def RecordGameResult(link,game,win,lose,units): p.zincrby(nzhtname+"nwon",tsh,1) p.zincrby(nzdtname+"nwon",tsd,1) if lose: - p.hincrby("balances",identity,-units) + p.hincrby("balances",account,-units) p.hincrby(tname,"lost",units) p.hincrby(rtname,"lost",units) p.hincrby(alltname,"lost",units) @@ -269,11 +271,11 @@ def RetrieveHouseBalance(force_refresh=False): house_balance = unlocked_balance user_balances=0 - identities = redis_hgetall("balances") - for identity in identities: - ib = long(identities[identity]) - house_balance = house_balance - ib - user_balances+=ib + accounts = redis_hgetall("balances") + for account in accounts: + ab = long(accounts[account]) + house_balance = house_balance - ab + user_balances+=ab earmarked_balances=0 earmarked = redis_hgetall("earmarked") @@ -296,9 +298,13 @@ def GetHouseBalance(link,cmd): try: balance = RetrieveHouseBalance() personal_balance=0 + seen_accounts=[] for network in networks: identity=network.name+':'+config.tipbot_name - personal_balance += long(redis_hget('balances',identity) or 0) + account=redis_hget('accounts',identity) + if not account in seen_accounts: + personal_balance += long(redis_hget('balances',account) or 0) + seen_accounts.append(account) except Exception,e: log_error('Failed to retrieve house balance: %s' % str(e)) link.send('An error occured') diff --git a/tipbot/link.py b/tipbot/link.py index bb3e7ff..be2f496 100644 --- a/tipbot/link.py +++ b/tipbot/link.py @@ -24,6 +24,12 @@ class Link: def __repr__(self): return '' % (str(self.network),str(self.user),str(self.group),str(self.data)) + def __eq__(self,link): + return self.identity()==link.identity() + + def __ne__(self,link): + return not self.__eq__(link) + def identity(self): return self.identity_string diff --git a/tipbot/modules/bookie.py b/tipbot/modules/bookie.py index ce4db7f..8998a52 100644 --- a/tipbot/modules/bookie.py +++ b/tipbot/modules/bookie.py @@ -120,7 +120,8 @@ def Cancel(link,cmd): for bettor in bettors: units = long(redis_hget(tname,bettor+":units")) log_info('Refunding %s to %s' % (AmountToString(units),bettor)) - p.hincrby('balances',bettor,units) + a = GetAccount(bettor) + p.hincrby('balances',a,units) p.hincrby('earmarked','bookie',-units) refundmsg.append('%s to %s' % (AmountToString(units), NickFromIdentity(bettor))) p.hdel('bookie:active',book_index) @@ -300,9 +301,10 @@ def Bet(link,cmd): log_info('%s wants to bet %s on %s' % (identity, AmountToString(units), outcome)) try: log_info('Bet: %s betting %s on outcome %s' % (identity, AmountToString(units), outcome)) + account = GetAccount(link) try: p = redis_pipeline() - p.hincrby("balances",identity,-units) + p.hincrby("balances",account,-units) p.hincrby("earmarked","bookie",units) p.hincrby(tname+":bets",outcome,units) p.hincrby(tname,"bets",units) @@ -359,11 +361,12 @@ def Result(link,cmd): o = redis_hget(tname,bettor+":outcome") ounits = long(redis_hget(tname,bettor+":units")) if o == outcome: + a = GetAccount(bettor) owinunits = long(total_units_bet * (1-config.bookie_fee) * ounits / total_units_bet_by_winners) if owinunits len(userlist): users = len(userlist) everyone = True @@ -148,10 +154,10 @@ def Rain(link,cmd): link.send("This would mean not even an atomic unit per nick") return log_info("%s wants to rain %s on %s users in %s" % (identity, AmountToString(units), users, group.name)) - log_log("eligible users in %s: %s" % (group.name, str(userlist))) + log_log("eligible users in %s: %s" % (group.name, str([user.identity() for user in userlist]))) random.shuffle(userlist) userlist = userlist[0:users] - log_log("selected users in %s: %s" % (group.name, userlist)) + log_log("selected users in %s: %s" % (group.name, [user.identity() for user in userlist])) user_units = long(units / users) enumerate_users = False @@ -163,13 +169,14 @@ def Rain(link,cmd): msg = "%s rained %s on:" % (link.user.nick, AmountToString(user_units)) enumerate_users = True pipe = redis_pipeline() - pipe.hincrby("balances",identity,-units) + pipe.hincrby("balances",account,-units) pipe.incrby("rain_total_count",1) pipe.incrby("rain_total_amount",units) pipe.hincrby("rain_count",identity,1) pipe.hincrby("rain_amount",identity,units) for user in userlist: - pipe.hincrby("balances",user,user_units) + a = GetAccount(user) + pipe.hincrby("balances",a,user_units) if enumerate_users: msg = msg + " " + NickFromIdentity(user) pipe.execute() @@ -223,7 +230,8 @@ def RainActive(link,cmd): units = long(amount * coinspecs.atomic_units) try: - balance = redis_hget("balances",identity) + account = GetAccount(link) + balance = redis_hget("balances",account) if balance == None: balance = 0 balance=long(balance) @@ -232,17 +240,20 @@ def RainActive(link,cmd): return now = time.time() - userlist = [user.identity() for user in link.network.get_active_users(seconds,group.name)] - log_log('userlist: %s' % str(userlist)) - userlist.remove(link.identity()) + userlist = link.network.get_active_users(seconds,group.name) + log_log('userlist: %s' % str([user.identity() for user in userlist])) + userlist.remove(link) for n in config.no_rain_to_nicks: - userlist.remove(IdentityFromString(link,n)) + i=IdentityFromString(link,n) + l=Link(link.network,User(link.network,NickFromIdentity(i)),group) + if l in userlist: + userlist.remove(l) weights=dict() weight=0 - log_log('userlist to loop: %s' % str(userlist)) + log_log('userlist to loop: %s' % str([user.identity() for user in userlist])) for n in userlist: - log_log('user to check: %s' % NickFromIdentity(n)) - t = link.network.get_last_active_time(NickFromIdentity(n),group.name) + log_log('user to check: %s' % n.user.nick) + t = link.network.get_last_active_time(n.user.nick,group.name) if t == None: continue dt = now - t @@ -256,7 +267,7 @@ def RainActive(link,cmd): return pipe = redis_pipeline() - pipe.hincrby("balances",identity,-units) + pipe.hincrby("balances",account,-units) pipe.incrby("arain_total_count",1); pipe.incrby("arain_total_amount",units); pipe.hincrby("arain_count",identity,1); @@ -269,9 +280,10 @@ def RainActive(link,cmd): user_units = long(units * weights[n] / weight) if user_units <= 0: continue - act = now - link.network.get_last_active_time(NickFromIdentity(n),link.group.name) - log_info("%s rained %s on %s (last active %f hours ago)" % (identity, AmountToString(user_units),n,act/3600)) - pipe.hincrby("balances",n,user_units) + act = now - link.network.get_last_active_time(n.user.nick,link.group.name) + log_info("%s rained %s on %s (last active %f hours ago)" % (identity, AmountToString(user_units),n.identity(),act/3600)) + a=GetAccount(n) + pipe.hincrby("balances",a,user_units) rained_units += user_units if not minu or user_units < minu: minu = user_units diff --git a/tipbot/modules/withdraw.py b/tipbot/modules/withdraw.py index a123996..157f905 100644 --- a/tipbot/modules/withdraw.py +++ b/tipbot/modules/withdraw.py @@ -77,8 +77,9 @@ def Withdraw(link,cmd): link.send("Sorry, withdrawal is disabled due to a wallet error which requires admin assistance") return + account = GetAccount(identity) try: - balance = redis_hget("balances",identity) + balance = redis_hget('accounts',account) if balance == None: balance = 0 balance=long(balance) @@ -133,7 +134,7 @@ def Withdraw(link,cmd): link.send( "Tx sent: %s" % tx_hash) try: - redis_hincrby("balances",identity,-amount) + redis_hincrby("balances",account,-amount) except Exception, e: log_error('Withdraw: FAILED TO SUBTRACT BALANCE: exception: %s' % str(e)) CheckDisableWithdraw() diff --git a/tipbot/utils.py b/tipbot/utils.py index 2aaaaad..48106af 100644 --- a/tipbot/utils.py +++ b/tipbot/utils.py @@ -19,6 +19,7 @@ from decimal import * import tipbot.config as config import tipbot.coinspecs as coinspecs from tipbot.log import log_error, log_warn, log_info, log_log +from tipbot.link import Link from tipbot.redisdb import * registered_networks=dict() @@ -284,10 +285,28 @@ def RetrieveTipbotBalance(force_refresh=False): cached_tipbot_unlocked_balance=unlocked_balance return balance, unlocked_balance +def GetAccount(link_or_identity): + if isinstance(link_or_identity,Link): + identity=link_or_identity.identity() + else: + identity=link_or_identity + account = redis_hget('accounts',identity) + if account == None: + log_info('No account found for %s, creating new one' % identity) + next_account_id = long(redis_get('next_account_id') or 0) + account = next_account_id + if redis_hexists('accounts',account): + raise RuntimeError('Next account ID already exists (%d)', account) + redis_hset('accounts',identity,account) + next_account_id += 1 + redis_set('next_account_id',next_account_id) + return account + def RetrieveBalance(link): try: - balance = redis_hget("balances",link.identity()) or 0 - confirming = redis_hget("confirming_payments",link.identity()) or 0 + account = GetAccount(link) + balance = redis_hget("balances",account) or 0 + confirming = redis_hget("confirming_payments",account) or 0 return long(balance), long(confirming) except Exception, e: log_error('RetrieveBalance: exception: %s' % str(e))