def expire(self): """ Expire a pending tip """ lg.debug("> HkAction::expire()") # Move coins back into self.u_from account lg.info("HkAction::expire(): moving %s %s from %s to %s", self.coinval, self.coin.upper(), self.haikuberu.conf.service[self.service].username, self.u_from.username) # Move coins from dogetipbot back to a.u_from account b = user.HkUser(self.haikuberu, self.service, self.haikuberu.conf.service[self.service].username) b.sub_coin(coin = self.coin, amount = self.coinval) self.u_from.add_coin(coin = self.coin, amount = self.coinval) # Save transaction as expired self.haikuberu.db.execute("UPDATE action SET state = 'expired' WHERE action_id = %s ", (self.action_id)) lg.debug("< HkAction::expire() DONE") return True
def decline(self): lg.debug("> HkAction::decline()") actions = get_actions(command='givetip', to_user = self.u_from.username, state = 'pending', haikuberu = self.haikuberu) if actions: for a in actions: # Move coins back into a.u_from account lg.info("HkAction::decline(): moving %s %s from %s to %s", a.coinval, a.coin.upper(), 'dogetipbot', a.u_from.username) # Move coins from dogetipbot back to a.u_from account b = user.HkUser(self.haikuberu, 'reddit', 'dogetipbot') b.sub_coin(coin=a.coin, amount=a.coinval) a.u_from.add_coin(coin=a.coin, amount=a.coinval) # Save transaction as declined a.save('declined') # Save action to database self.save('failed') lg.debug("< HkAction::decline() DONE") return True
def givetip(self, is_pending=False): # Debug lg.debug("> HkAction::givetip()") my_id = "NoMessageID" self.is_pending = is_pending # Return value assumes failure return_value = False # Set message ID (unique ID) if there is one if self.msg_id: my_id = self.msg_id # Check if action has been processed if check_action(command = self.command, msg_id = my_id, haikuberu = self.haikuberu, is_pending = is_pending, service = self.service): # Found action in database, returning lg.warning("HkAction::givetip(): duplicate action %s (msg.id %s), ignoring", self.command, my_id) return False # Validate action if not self.validate(is_pending = is_pending): # Couldn't validate action, returning return False # Sending to a user if self.u_to: # Pending check if is_pending: # This is accept() of pending transaction, so move coins from pending account to receiver lg.info("HkAction::givetip(): moving %f %s from %s to %s...", self.coinval, self.coin.upper(), 'dogetipbot', self.u_to.username) b = user.HkUser(self.haikuberu, self.service, self.haikuberu.conf.service[self.service].username) b.sub_coin(coin=self.coin, amount=self.coinval) self.u_to.add_coin(coin=self.coin, amount=self.coinval) else: # This is not accept() of pending transaction, so move coins from tipper to receiver lg.info("HkAction::givetip(): moving %f %s from %s to %s...", self.coinval, self.coin.upper(), self.u_from.username, self.u_to.username) self.u_from.sub_coin(coin=self.coin, amount=self.coinval) self.u_to.add_coin(coin=self.coin, amount=self.coinval) # Transaction succeeded (save returns True on success) return_value = self.save('completed') elif self.addr_to: # Process tip to address try: lg.info("HkAction::givetip(): sending %f %s to %s...", self.coinval, self.coin, self.addr_to) # Send withdraw to blockchain self.txid = self.haikuberu.coins[self.coin].sendtoaddr(_userfrom=self.u_from.username, _addrto=self.addr_to, _amount=self.coinval) # Subtract coins from user account self.u_from.sub_coin(coin=self.coin, amount=self.coinval) # Transaction is pending until confirmed return_value = self.save('pending') # Put in unprocessed table for confirmation check self.haikuberu.db.execute("INSERT INTO unprocessed SET txid = '" + self.txid + "' ") except Exception as e: # Transaction failed self.save('failed') lg.error("HkAction::givetip(): sendtoaddr() failed") # Now send notifications self.tip_notification() # Done lg.debug("< HkAction::givetip() DONE") return None
def __init__(self, haikuberu=None, msg=None, deleted_msg_id = None, deleted_created_utc=None): # Debug lg.debug("> HkAction::__init__() BEGIN INIT") # Make sure message and haikuberu object were passed if not bool(msg): raise Exception("HkAction::__init__: Message not set, this should never happen") if not bool(haikuberu): raise Exception("HkAction::__init__: Haikuberu obj not set, this should never happen") self.msg = json.loads(msg['body']) self.haikuberu = haikuberu # Queue ID self.queue_id = msg['id'] if 'id' in msg else '' self.queue_res_id = msg['reservation_id'] if 'reservation_id' in msg else '' # Error self.error = '' self.state = '' # Config variables self.config1 = None self.config2 = None self.config3 = None self.config4 = None self.config5 = None self.config6 = None self.config7 = None self.config8 = None self.config9 = None self.config10 = None # Action ID self.action_id = self.msg.get("action_id", None) # Command / type self.service = self.msg['service'] self.service_id = hkservice.HkService(self.haikuberu).get_from_name(self.service) self.command = self.msg['type'] self.u_from = self.msg['u_from'] # Currency self.coin = 'dog' self.fiat = self.msg.get("fiat", None) self.coinval = self.msg.get('coin_val', None) self.fiatval = self.msg.get("fiatval", None) self.fiat = self.msg.get("fiat", None) # Reddit specific self.msg_id = self.msg.get("msgid", None) self.created_utc = self.msg.get("created_utc", None) self.verify = self.msg.get("verify", None) self.subreddit = self.msg.get('subreddit', None) self.fullname = self.msg.get('fullname', None) # Twitch specific self.channel = self.msg.get("channel", None) # Twitter specific self.tweet_id = self.msg.get("tweet_id", None) # Disqus specific self.post_id = self.msg.get("post_id", None) self.thread_id = self.msg.get("thread_id", None) # Set configuration field values if self.service == 'reddit': self.config1 = self.msg_id self.config2 = self.fullname self.config3 = self.subreddit self.config4 = self.msg.get("msg_link", None) self.config5 = self.msg.get("verify", None) elif self.service == 'twitch': self.config1 = self.channel elif self.service == 'twitter': self.config1 = self.tweet_id elif self.service == 'disqus': self.config1 = self.post_id self.config2 = self.thread_id # Address self.addr_to = self.msg.get("addr_to", None) self.u_to = self.msg.get('u_to', None) self.u_to_service = self.msg.get('u_to_service', None) # To and from user objects self.u_to = user.HkUser(haikuberu, self.service, self.u_to) if bool(self.u_to) else None self.u_from = user.HkUser(haikuberu, self.service, self.u_from) if self.coinval == 'all': if self.u_from.is_registered(): self.coinval = self.u_from.get_balance(self.coin) else: self.coinval = 0 # Sanity check if not bool(self.service): raise Exception("HkAction::__init__: Service not set in message") if not bool(self.command): raise Exception("HkAction::__init__: Type of command not set in message") if not bool(self.u_from): raise Exception("HkAction::__init__: u_from not set in message") if self.command in ['givetip', 'withdraw']: if not (bool(self.u_to) ^ bool(self.addr_to)): raise Exception("HkAction::__init__(command=%s): u_to xor addr_to must be set" % (self.command)) # Convert coinval and fiat to decimal, if necesary if self.coinval and type(self.coinval) == unicode and self.coinval.replace('.', '').isnumeric(): self.coinval = Decimal(self.coinval) if self.fiatval and type(self.fiatval) == unicode and self.fiatval.replace('.', '').isnumeric(): self.fiatval = Decimal(self.fiatval) # Truncate precisoin if self.coinval: self.coinval = Decimal(str(self.coinval).replace(',','')) lg.debug("HkAction::init() Converting coinval to decimal %s", self.coinval) self.coinval = Decimal(Decimal(trunc(self.coinval * 100000000)) / 100000000) lg.debug("< HkAction::__init__() DONE")
def validate(self, is_pending=False): """ Validate an action """ lg.debug("> HkAction::validate()") if self.command in ['givetip', 'withdraw']: # Fiat yo self.fiat = 'usd' if self.coinval == None: self.coinval = 0 self.fiatval = self.haikuberu.coin_value('dog', 'usd') * self.coinval # Final check - is this a to_addr transaction and is the address owned by dogetipbot? if self.addr_to: # Address validation try: if not addressvalidate.is_dogecoin_address(self.addr_to): raise ValueError("Not an address") except ValueError: self.save('failed', 'addr_invalid') self.tip_notification() return False sqlcheck = "SELECT user_id from address where address = %s " mysqlrow = self.haikuberu.db.execute(sqlcheck,(self.addr_to)).fetchone() lg.debug('HkAction::validate(): Checking if user is sending to a dogetipbot address') lg.debug(sqlcheck, (self.addr_to)) if not mysqlrow: lg.debug("HkAction::givetip(%s): external address, hit the blockchain",self.addr_to) else: # Address is owned by dogetipbot, now figure out service/username lg.debug("HkAction::givetip(%s): sneaky m**********r! found a user_id %s", self.addr_to, mysqlrow['user_id']) user_id = mysqlrow['user_id'] sql = "SELECT username.username, service.service_name FROM username JOIN service ON service.service_ID = username.service_id where username.user_id = %s AND username.service_id = %s" mysqlrow = self.haikuberu.db.execute(sql,(user_id, self.service_id)).fetchone() if not mysqlrow: lg.debug('HkAction::givetip(): Failed in a bad spot, no username/service found for user_id THIS SHOULDNT HAPPEN') else: self.u_to=user.HkUser(self.haikuberu, mysqlrow['service_name'], mysqlrow['username']) lg.debug("HkAction::givetip(%s): sneaky m**********r! it's really %s from %s service",self.addr_to,mysqlrow['username'], mysqlrow['service_name']) # Check if u_from has registered if not self.u_from.is_registered(): lg.debug("HkAction::validate(): %s", 'From User Not Registered') self.save('failed', 'not_registered') self.tip_notification() return False # Verify that u_from has coin address if not self.u_from.get_addr(coin=self.coin): lg.error("HkAction::validate(): user %s doesn't have %s address", self.u_from.username, self.coin.upper()) self.save('failed') return False # Verify minimum transaction size txkind = 'givetip' if self.u_to else 'withdraw' if self.coinval < self.haikuberu.conf.coins[self.coin].minconf[txkind]: lg.debug("HkAction::validate(): tip below minimum amt CHEAP ASS") self.save('failed', 'tip_below_minimum') self.tip_notification() return False # Verify balance (unless it's a pending transaction being processed, in which case coins have been already moved to pending acct) if self.u_to and not is_pending: # Tip to user (requires less confirmations) balance_avail = self.u_from.get_balance(coin=self.coin) if(balance_avail < self.coinval): lg.debug("HkAction::validate(): Not Enough Coins To send the tip") self.save('failed', 'balance_too_low') self.tip_notification() return False elif self.addr_to: # Tip/withdrawal to address (requires more confirmations) balance_avail = self.u_from.get_balance(coin=self.coin) if balance_avail < self.coinval: lg.debug("HkAction::validate(): Im pretty sure this is just a repetetive fail") self.save('failed') return False # Check if u_to has any pending coin tips from u_from if self.u_to and not is_pending: if check_action(command='givetip', state='pending', to_user=self.u_to.username, from_user=self.u_from.username, coin=self.coin, haikuberu=self.haikuberu, service=self.service): lg.debug("HkAction::validate(): TIP FAILED") self.save('failed') return False # Check if u_to has registered, if applicable if self.u_to and not self.u_to.is_registered(): # u_to not registered: # - move tip into pending account # - save action as 'pending' # - notify u_to to accept tip <<< LOL FIGURE OUT ON YOUR OWN b = user.HkUser(self.haikuberu, self.service, self.haikuberu.conf.service[self.service].username) # Move coins into pending account minconf = self.haikuberu.coins[self.coin].conf.minconf.givetip lg.info("HkAction::validate(): moving %s %s from %s to %s (minconf=%s)...", self.coinval, self.coin.upper(), self.u_from.username, self.haikuberu.conf.service[self.service].username, minconf) # move from user to dogetipbot self.u_from.get_balance(coin=self.coin) b.get_balance(coin=self.coin) self.u_from.sub_coin(coin=self.coin, amount=self.coinval) b.add_coin(coin=self.coin, amount=self.coinval) # Save action as pending self.save('pending') # Send pending notifications self.tip_notification() # Action saved as 'pending', return false to avoid processing it further return False # Validate addr_to, if applicable if self.addr_to: if not self.haikuberu.coins[self.coin].validateaddr(_addr=self.addr_to): lg.debug("HkAction::validate(): address not valid") self.save('failed', 'addr_invalid') self.tip_notification() return False # Validate motherfucking balance if its a withdraw and there is not user_to set if self.addr_to and not self.u_to: hotwallet_amt = self.haikuberu.coins['dog'].conn.getbalance() if (self.coinval > hotwallet_amt): lg.debug("HkAction::validate(): HOT WALLET DEPLETED") self.save('failed') if self.haikuberu.conf.misc.notify.enabled: self.haikuberu.notify(_msg="Transaction exceeded hot wallet balance. User affected: " + self.u_from.username + " " + str(self.coinval)) return False # Action is valid lg.debug("< HkAction::validate() DONE") return True
def gold(self): lg.debug("HkAction::history()") if not self.u_from.is_registered(): self.save('failed', 'not_registered') return self.error_notification('not_registered') # If there is a fiat issue, return if self.haikuberu.coin_value('dog', 'usd') <= 0: self.save('failed', 'fiat_error') self.error_notification('fiat_error') return self # Calculate the fiat and round to nearest 100 self.coinval = trunc(4 / self.haikuberu.coin_value('dog', 'usd')) self.coinval -= self.coinval % 100 self.fiatval = 4 # Fiat sanity check if self.coinval < 10000: self.save('failed', 'fiat_error') self.error_notification('fiat_error') return self # Check if u_from has registered if not self.u_from.is_registered(): self.save('failed', 'not_registered') self.error_notification('not_registered') return self print self.coinval # Check u_from balance balance_avail = self.u_from.get_balance(coin=self.coin) if(balance_avail < self.coinval): self.save('failed', 'balance_too_low') self.error_notification('balance_too_low') return self # Move coins self.u_from.sub_coin(self.coin, self.coinval) reddit_bot = user.HkUser(self.haikuberu, 'reddit', 'dogetipbot') reddit_bot.add_coin(self.coin, self.coinval) self.save('completed') # Base notification data data = { 'type' : 'gold_sent', 'service' : self.service, 'command' : self.command, 'u_from' : self.u_from.username, 'u_to' : self.u_to.username, 'addr_from' : self.u_from.get_addr('dog'), 'coinval' : self.coinval, 'fiatval' : self.fiatval, 'config1' : self.config1, 'config2' : self.config2, 'config3' : self.config3, 'config4' : self.config4, 'config5' : self.config5, 'config6' : self.config6, 'config7' : self.config7, 'config8' : self.config8, 'config9' : self.config9, 'config10' : self.config10, } self.haikuberu.push_messasge_out(json.dumps(data)) self.notification.append(data.copy()) if self.u_to and not self.u_to.is_registered(): data['type'] = 'gold_received' self.haikuberu.push_messasge_out(json.dumps(data)) self.notification.append(data.copy()) return self