def stopMonitor(update, context): chatId = update.effective_chat.id numAccounts = AlgoWatcherAcct.objects(chatId=chatId).count() accounts = AlgoWatcherAcct.objects(chatId=chatId) args = util.parseArgs(context.args) if 0 == numAccounts: context.bot.send_message( chat_id=chatId, text="No accounts registered. Use /addAcct to register an account") return if 1 == numAccounts: acctIndex = 0 elif not 'acctindex' in args or int(args['acctindex']) < 0 or int( args['acctindex']) >= numAccounts: context.bot.send_message( chat_id=chatId, text= "Invalid account index provided. Pick valid index from list below: " ) listAccts(update, context) return else: acctIndex = int(args['acctindex']) accounts[acctIndex].update(monitorEnable=False) context.bot.send_message( chat_id=update.effective_chat.id, parse_mode=telegram.ParseMode.MARKDOWN, text="Monitor disabled for " + getFormattedName( accounts[acctIndex])) #accounts[acctIndex]['address'])
def deleteAcct(update, context): chatId = update.effective_chat.id numAccounts = AlgoWatcherAcct.objects(chatId=chatId).count() args = util.parseArgs(context.args) if numAccounts > 0: accounts = AlgoWatcherAcct.objects(chatId=chatId) if 1 == numAccounts: acctIndex = 0 elif 'acctindex' in args and int(args['acctindex']) >= 0 and int( args['acctindex']) < numAccounts: acctIndex = int(args['acctindex']) else: context.bot.send_message( chat_id=chatId, text= "Invalid account index provided. Pick valid index from list below: " ) listAccts(update, context) return accounts[acctIndex].delete() context.bot.send_message(chat_id=chatId, text="Deleted Acct #{}".format(acctIndex)) listAccts(update, context) else: context.bot.send_message( chat_id=chatId, text="No accounts registered. Use /addAcct to register an account")
def getAssetBalanceCmd(update, context): chatId = update.effective_chat.id numAccounts = AlgoWatcherAcct.objects(chatId=chatId).count() accounts = AlgoWatcherAcct.objects(chatId=chatId) args = util.parseArgs(context.args) if not 'assetid' in args: context.bot.send_message(chat_id=update.effective_chat.id, text="No ASA Asset Id specified") return if 0 == numAccounts: context.bot.send_message( chat_id=update.effective_chat.id, text="No accounts registered. Use /addAcct to register an account") return if 1 == numAccounts: acctIndex = 0 elif numAccounts > 1 and (not 'acctindex' in args or int(args['acctindex']) < 0 or int(args['acctindex']) >= numAccounts): context.bot.send_message( chat_id=chatId, text= "Invalid account index provided. Pick valid index from list below: " ) listAccts(update, context) else: acctIndex = int(args['acctindex']) #The Indexer must be used to get ASA Meta data such as unit-name and #this requires an archival node. Instead of running my own archical ndoe #I instead grab this information using the AlgoExploer API algoExplorerAssetUrl = "https://api.algoexplorer.io/idx2/v2/assets/" algoExplorerAssetUrl = algoExplorerAssetUrl + str(args['assetid']) asset_info = json.loads(requests.get(algoExplorerAssetUrl).text) #Make sure ASA ID provided is valid if "asset" in asset_info: try: balance = getAssetBalance(accounts[acctIndex]['address'], args['assetid']) scaleFactor = 10**(-1 * asset_info["asset"]["params"]["decimals"]) balance = balance * scaleFactor units = asset_info["asset"]["params"]["unit-name"] message = accounts[acctIndex][ 'address'] + "\nAccount Balance for Asset ID " + str( args['assetid']) + ": {}".format(balance) + " " + units except: message = "No Balance found for Asset ID {} for Account{}\n ".format( args['assetid'], accounts[acctIndex]['address']) else: message = "Invalid Asset ID {}".format(args['assetid']) context.bot.send_message(chat_id=update.effective_chat.id, text=message)
def startMonitor(update, context): chatId = update.effective_chat.id numAccounts = AlgoWatcherAcct.objects(chatId=chatId).count() accounts = AlgoWatcherAcct.objects(chatId=chatId) args = util.parseArgs(context.args) if 0 == numAccounts: context.bot.send_message( chat_id=chatId, text="No accounts registered. Use /addAcct to register an account") return if 1 == numAccounts: acctIndex = 0 elif not 'acctindex' in args or int(args['acctindex']) < 0 or int( args['acctindex']) >= numAccounts: context.bot.send_message( chat_id=chatId, text= "Invalid account index provided. Pick valid index from list below: " ) listAccts(update, context) return else: acctIndex = int(args['acctindex']) if 'interval' in args: interval = util.getInterval(args['interval']) accounts[acctIndex].update(interval=interval) if 'txnsperinterval' in args: if int(args['txnsperinterval']) >= 0: accounts[acctIndex].update( txnsPerInterval=int(args['txnsperinterval'])) accounts[acctIndex].update(monitorEnable=True) accounts[acctIndex].update(monitorTime=datetime.utcnow()) #txStr = accounts[acctIndex]['address'] + " for " + str(accounts[acctIndex]['txnsPerInterval']) txStr = getFormattedName(accounts[acctIndex]) + " for " + str( accounts[acctIndex]['txnsPerInterval']) txStr = txStr + " " + ("transactions" if accounts[acctIndex]['txnsPerInterval'] != 1 else "transaction") message = "Monitor Enabled. Monitoring " + txStr + " every " + util.intervalToStr( accounts[acctIndex]['interval']) context.bot.send_message(chat_id=update.effective_chat.id, parse_mode=telegram.ParseMode.MARKDOWN, text=message)
def listAccts(update, context): chatId = update.effective_chat.id accounts = AlgoWatcherAcct.objects(chatId=chatId) if len(accounts) > 0: message = "Accounts:\n" i = 0 for account in accounts: name = '' if len(account['alias']) > 0: name = " (*{}*)".format(account['alias']) message = message + "Acct {}{}: ".format( i, name) + account['address'] + " - txnsPerInterval: {}".format( account['txnsPerInterval']) + ", interval: {}".format( util.intervalToStr(account['interval']) ) + ", monitorEnabled: {}\n".format( account['monitorEnable']) i += 1 context.bot.send_message(chat_id=chatId, parse_mode=telegram.ParseMode.MARKDOWN, text=message) else: context.bot.send_message( chat_id=chatId, text="No accounts registered. Use /addAcct to register an account")
def getLastPlanetPayoutCmd(update, context): chatId = update.effective_chat.id addresses = AlgoWatcherAcct.objects(chatId=chatId).distinct('address') if len(addresses) > 0: message = "" for algoAddress in addresses: try: [amount, round_time, note] = getLastPlanetPayout(algoAddress) timestamp = datetime.fromtimestamp( round_time, tz=timezone.utc ).strftime( "%B %d, %Y %H:%M:%S UTC" ) #datetime.utcfromtimestamp(round_time).strftime("%B %d, %Y %H:%M:%S UTC") planet_str = format(amount, '.3f') + " PLANET" message = message + "{} paid out on {} to {} with note:\n {}\n\n".format( planet_str, timestamp, algoAddress, base64.b64decode(note)) except Exception as e: message = message + "No Planet Payouts found for account {}\n\n".format( algoAddress) print(e) else: message = "No accounts registered. Use /addAcct to register an account" context.bot.send_message(chat_id=update.effective_chat.id, text=message)
def addAcct(update, context): algoAddress = '' if len(context.args) > 0: chatId = update.effective_chat.id symbolsToRemove = "!@<>#." algoAddress = context.args[0].lstrip(symbolsToRemove).rstrip( symbolsToRemove) account = AlgoWatcherAcct(chatId=chatId, address=algoAddress, monitorEnable=False, txnsPerInterval=1, interval=600, monitorTime=datetime.utcnow(), alias="") account.save() message = "Registered Algorand account " + algoAddress + " \n Total Accounts Registered: {}".format( AlgoWatcherAcct.objects(chatId=chatId).count()) else: message = "No Address provided" context.bot.send_message(chat_id=update.effective_chat.id, text=message)
def updateAlias(update, context): chatId = update.effective_chat.id numAccounts = AlgoWatcherAcct.objects(chatId=chatId).count() args = util.parseArgs(context.args) if numAccounts > 0: accounts = AlgoWatcherAcct.objects(chatId=chatId) if 1 == numAccounts: acctIndex = 0 elif 'acctindex' in args and int(args['acctindex']) >= 0 and int( args['acctindex']) < numAccounts: acctIndex = int(args['acctindex']) else: context.bot.send_message( chat_id=chatId, text= "Invalid account index provided. Pick valid index from list below: " ) listAccts(update, context) return try: accounts[acctIndex].update(alias=args['name']) context.bot.send_message(chat_id=chatId, text="Set Alias for {} to {}".format( accounts[acctIndex]["address"], accounts[acctIndex]["alias"])) except: context.bot.send_message( chat_id=chatId, text= "Error setting Alias with input arguments. Usage /alias acctIndex=Number name=Name" ) else: context.bot.send_message( chat_id=chatId, text="No accounts registered. Use /addAcct to register an account")
def monitorAsset(dispatcher): while True: #Get all monitor enabled accounts sorted by earliest time accounts = AlgoWatcherAcct.objects( monitorEnable=True).order_by('monitorTime') for account in accounts: elapsedTime = (datetime.utcnow() - account['monitorTime']).total_seconds() if elapsedTime >= account['interval']: try: account.update(monitorTime=datetime.utcnow()) numTxns = len( getPlanetTxns(account['address'], account['monitorTime'])) if numTxns < account['txnsPerInterval']: message = "No New Planet Transactions Detected for " + getFormattedName( account) #account['address'] if account['txnsPerInterval'] > 1: message = message + ": Expected {} transactions | Got {} transaction{}".format( account['txnsPerInterval'], numTxns, "s" if numTxns != 1 else "") message = message + ". Please make sure your Sensor and App are still active." dispatcher.bot.send_message( chat_id=account['chatId'], parse_mode=telegram.ParseMode.MARKDOWN, text=message) except Exception as e: try: dispatcher.bot.send_message( chat_id=account['chatId'], parse_mode=telegram.ParseMode.MARKDOWN, text="Unable to get transaction status for {}". format(getFormattedName( account))) #account['address'])) print( "Unable to get transaction status for User {} (id #{}) address #{}" .format( dispatcher.bot.get_chat( account['chatId']).username, account['chatId'], account['address'])) print("Exception: {}".format(e)) except Exception as e: print("Alerting user {} of failure failed: Reason {}". format(account['chatId'], e)) sleep(1)
def getAveragePlanetPayoutCmd(update, context): chatId = update.effective_chat.id addresses = AlgoWatcherAcct.objects(chatId=chatId).distinct('address') if len(addresses) > 0: message = "" for algoAddress in addresses: try: amount = getAveragePlanetPayout(algoAddress) message = message + "{}\n{} PLANET paid out on average over the last 7 days\n\n".format( algoAddress, amount) except: message = message + "No Planet Payouts found for {}\n\n".format( algoAddress) else: message = "No accounts registered. Use /addAcct to register an account" context.bot.send_message(chat_id=chatId, text=message)
def getPlanetBalance(update, context): global algoClient global planetAssetId chatId = update.effective_chat.id addresses = AlgoWatcherAcct.objects(chatId=chatId).distinct('address') if len(addresses) > 0: message = "" for algoAddress in addresses: try: balance = getAssetBalance(algoAddress, planetAssetId) * 1e-6 message = message + "Account {} Balance: {} PLANET\n".format( algoAddress, format(balance, '.3f')) except: message = message + "Error getting balance for Account {}\n".format( algoAddress) else: message = "No accounts registered. Use /addAcct to register an account" context.bot.send_message(chat_id=chatId, text=message)
def getAlgoBalance(update, context): global algoClient chatId = update.effective_chat.id addresses = AlgoWatcherAcct.objects(chatId=chatId).distinct('address') if len(addresses) > 0: message = "" for algoAddress in addresses: try: account_info = algoClient.account_info(algoAddress) balance = account_info.get('amount') * 1e-6 message = message + "Account {} Balance: {} ALGO\n".format( algoAddress, format(balance, '.6f')) except: message = message + "Error getting balance for Account {}\n".format( algoAddress) else: message = "No accounts registered. Use /addAcct to register an account" context.bot.send_message(chat_id=chatId, text=message)
def getStats(update, context): numUsers = AlgoWatcherAcct.objects().distinct('chatId') numAddresses = AlgoWatcherAcct.objects().count() message = "Number of registered users {} watching {} addresses".format( len(numUsers), numAddresses) context.bot.send_message(chat_id=update.effective_chat.id, text=message)