def networkUpdate(bot, ids, added): count = len(ids) logger.info("networkUpdate {}, {}".format(count, added)) response = messages.markdown("<u><b>Network update<b><u>\n\n", bot.messenger) if added: response += "{} new node{} detected\n\n".format( count, "s" if count > 1 else "") else: response += "{} node{} left us!\n\n".format(abs(count), "s" if count < 1 else "") with bot.nodeList as nodeList: response += messages.markdown( "We have <b>{}<b> created nodes now!\n\n".format(nodeList.count()), bot.messenger) response += messages.markdown( "<b>{}<b> of them are enabled.".format(nodeList.enabled()), bot.messenger) return response
def detail(bot, update): response = messages.markdown("<u><b>Detail<b><u>\n\n", bot.messenger) userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo[ 'name'] if 'name' in userInfo else update.message.from_user.name logger.debug("detail - user: {}".format(userId)) nodesFound = False user = bot.database.getUser(userId) userNodes = bot.database.getAllNodes(userId) if user == None or userNodes == None or len(userNodes) == 0: response += messages.nodesRequired(bot.messenger) else: with bot.nodeList as nodeList: minimumUptime = nodeList.minimumUptime() top10 = nodeList.enabledWithMinProtocol() * 0.1 for userNode in userNodes: masternode = nodeList.getNodes([userNode['collateral']])[0] response += messages.markdown( ("<b>" + userNode['name'] + " - " + masternode.ip + "<b>"), bot.messenger) response += "\n `Status` " + masternode.status response += "\n `Position` " + messages.markdown( masternode.positionString(minimumUptime, top10), bot.messenger) response += "\n `Payee` " + masternode.payee response += "\n `Active since` " + util.secondsToText( masternode.activeSeconds) response += "\n `Last seen` " + util.secondsToText( int(time.time()) - masternode.lastSeen) response += "\n `Last payout (Block)` " + masternode.payoutBlockString( ) response += "\n `Last payout (Time)` " + masternode.payoutTimeString( ) response += "\n `Protocol` {}".format(masternode.protocol) #response += "\n `Rank` {}".format(masternode.rank) response += "\n " + messages.link( bot.messenger, 'https://explorer3.curium.cc/address/{}'.format( masternode.payee), 'Open the explorer!') response += "\n\n" return response
def nodes(bot, update): response = messages.markdown("<u><b>Nodes<b><u>\n\n", bot.messenger) userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else None logger.debug("nodes - user: {}".format(userId)) nodesFound = False user = bot.database.getUser(userId) userNodes = bot.database.getAllNodes(userId) if user == None or userNodes == None or len(userNodes) == 0: response += messages.nodesRequired(bot.messenger) else: with bot.nodeList as nodeList: collaterals = list(map(lambda x: x['collateral'], userNodes)) nodes = nodeList.getNodes(collaterals) minimumUptime = nodeList.minimumUptime() top10 = nodeList.enabledWithMinProtocol() * 0.1 for masternode in sorted(nodes, key=lambda x: x.position if x.position > 0 else 100000): userNode = bot.database.getNodes(masternode.collateral, user['id']) payoutText = util.secondsToText(masternode.lastPaidTime) response += messages.markdown( "<b>" + userNode['name'] + "<b> - `" + masternode.status + "`", bot.messenger) response += "\nPosition " + messages.markdown( masternode.positionString(minimumUptime, top10), bot.messenger) response += "\nLast seen " + util.secondsToText( int(time.time()) - masternode.lastSeen) response += "\nLast payout " + masternode.payoutTimeString() response += "\n" + messages.link( bot.messenger, 'https://explorer3.curium.cc/address/{}'.format( masternode.payee), 'Open the explorer!') response += "\n\n" return response
def balances(bot, userId, results): response = messages.markdown("<u><b>Balances<b><u>\n\n", bot.messenger) if results != None: userNodes = bot.database.getAllNodes(userId) total = 0 error = False for result in results: for node in userNodes: if str(result.node.collateral) == node['collateral']: if not util.isInt(result.data) and "error" in result.data: response += "{} - Error: {}\n".format( node['name'], result.data["error"]) logger.warning("Balance response error: {}".format( result.data)) error = True else: try: total += round(result.data, 1) response += "{} - {} SMART\n".format( node['name'], result.data) except: error = True logger.warning( "Balance response invalid: {}".format( result.data)) response += "{} - Error: Could not fetch this balance.\n".format( node['name']) response += messages.markdown( "\nTotal: <b>{} SMART<b>".format(round(total, 1)), bot.messenger) # Only show the profit if there was no error since it would make not much sense otherwise. if not error: response += messages.markdown( "\nProfit: <b>{} SMART<b>".format( round(total - len(userNodes) * 10000, 1)), bot.messenger) else: response += "Sorry, could not check your balances! Looks like all explorers are down. Try it again later.\n\n" return response
def me(bot, update): response = messages.markdown("<u><b>User info<b><u>\n\n", bot.messenger) userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None #Get the user entry from the user which fired the command user = bot.database.getUser(userId) if user == None: response += messages.nodesRequired(bot.messenger) else: response += "You are {}\n\n".format( messages.removeMarkdown(user['name'])) response += "Status Notifications " + messages.notificationState( bot.messenger, user['status_n']) response += "\nReward Notifications " + messages.notificationState( bot.messenger, user['reward_n']) response += "\nTimeout Notifications " + messages.notificationState( bot.messenger, user['timeout_n']) response += "\nNetwork Notifications " + messages.notificationState( bot.messenger, user['network_n']) return response
def username(bot, update, args): response = messages.markdown("<u><b>Change username<b><u>\n\n", bot.messenger) userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None #Get the user entry from the user which fired the command user = bot.database.getUser(userId) if user == None: response += messages.nodesRequired(bot.messenger) elif len(args) != 1: response += messages.userNameRequiredError(bot.messenger) elif not util.validateName(args[0]): response += messages.invalidNameError.format(args[0]) else: old = user['name'] bot.database.updateUsername(args[0], user['id']) response += "Username updated from {} to {}".format( messages.removeMarkdown(old), messages.removeMarkdown(args[0])) return response
def watchlist(bot, message): logger.info("watchlist") response = "<u><b>Your watchlist<b><u>\n\n" userInfo = util.crossMessengerSplit(message) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else "Unknown" public = userInfo['public'] dbUser = bot.database.getUser(userId) if not dbUser: logger.error("User not in db?!") response += "<b>Unexpected error. Contact the team!<b>" else: watchlist = bot.database.getWatchlist(userId=userId) if not watchlist or not len(watchlist): logger.info("No watchlist entry!") response += messages.noWatchlistEntry(bot.messenger) else: proposalIds = list(map(lambda x: x['proposal_id'], watchlist)) watchlist = bot.proposals.getProposals(proposalIds) response += proposalList(bot, watchlist) return messages.markdown(response, bot.messenger)
def detail(bot, args): logger.info("detail") response = messages.markdown("<u><b>Proposal detail<b><u>\n\n", bot.messenger) if len(args): proposalIds = [] for arg in args: try: proposalIds.append(int(arg)) except: response += "Invalid argument: {}\n\n".format( messages.removeMarkdown(arg)) for proposalId in proposalIds: proposal = bot.proposals.getProposal(proposalId) if proposal: response += messages.proposalDetail(bot.messenger, proposal) else: response += "There is no info about the ID {}!\n\n".format( proposalId) return response
def changeState(bot, update, args, action, description): response = messages.markdown( "<b>{} notifications<b>\n\n".format(description), bot.messenger) userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None #Get the user entry from the user which fired the command user = bot.database.getUser(userId) if user == None: response += messages.nodesRequired(bot.messenger) elif len(args) != 1: response += messages.notificationArgumentRequiredError(bot.messenger) elif not util.isInt(args[0]) or int(args[0]) < 0 or int(args[0]) > 1: response += messages.notificationArgumentInvalidError(bot.messenger) else: action(user['id'], args[0]) response += messages.notificationResponse(bot.messenger, description.lower(), int(args[0])) return response
def info(bot, update): logger.info("network") response = messages.markdown("<u><b>SmartNode Network<b><u>\n\n", bot.messenger) with bot.nodeList as nodeList: if nodeList.synced() and nodeList.enabled(): lastBlock = nodeList.lastBlock created = nodeList.count() enabled = nodeList.enabled() preEnabled = nodeList.preEnabled expired = nodeList.expired newStartRequired = nodeList.newStartRequired qualifiedNormal = nodeList.qualifiedNormal qualifiedUpgrade = nodeList.qualifiedUpgrade upgradeModeDuration = nodeList.remainingUpgradeModeDuration protocolRequirement = nodeList.protocolRequirement() protocolOld = nodeList.count(nodeList.oldProtocol) protocolNew = nodeList.count(nodeList.newProtocol) initialWait = nodeList.minimumUptime() minPosition = int(enabled * 0.1) aberration = bot.aberration # Fallback if for whatever reason the top node could not filtered which # should actually not happen. top10Seconds = (int( (qualifiedNormal * 55) / 0.5) * (1 + bot.aberration)) topNode = list( filter(lambda x: x.position == minPosition, nodeList.nodes.values())) if len(topNode) and topNode[0].lastPaidTime: top10FromList = time.time() - topNode[0].lastPaidTime if top10FromList < 1.2 * top10Seconds: top10Seconds = top10FromList top10Time = util.secondsToText(top10Seconds) if upgradeModeDuration: upgradeModeDuration = util.secondsToText(upgradeModeDuration) response += messages.networkState( bot.messenger, lastBlock, created, preEnabled, enabled, expired, newStartRequired, qualifiedNormal, qualifiedUpgrade, upgradeModeDuration, protocolRequirement, nodeList.oldProtocol, nodeList.newProtocol, protocolOld, protocolNew, util.secondsToText(initialWait), top10Time, aberration) else: response += messages.notSynced(bot.messenger) return response
def stats(bot): logger.info("stats") response = messages.markdown("<u><b>Statistics<b><u>\n\n", bot.messenger) response += "User: {}\n".format(len(bot.database.getUsers())) response += "Nodes: {}\n".format(len(bot.database.getAllNodes())) return response
def balances(bot, userId, results): response = messages.markdown("<u><b>Balances<b><u>\n\n", bot.messenger) if results != None: userNodes = bot.database.getAllNodes(userId) total = 0 for result in results: for node in userNodes: if str(result.node.collateral) == node['collateral']: if not isinstance(result.data, dict) or not "balance" in result.data: response += "{} - Error: {}\n".format( node['name'], "Could not fetch balance.") logger.warning("Balance response error: {}".format( result.data)) else: try: balance = float(result.data["balance"]) total += round(balance, 1) response += "{} - {:,} SMART\n".format( node['name'], balance) except: logger.warning( "Balance response invalid: {}".format( result.data)) response += "{} - Error: Could not fetch this balance.\n".format( node['name']) response += messages.markdown( "\nTotal: <b>{:,} SMART<b>".format(round(total, 1)), bot.messenger) else: response += "Sorry, could not check your balances! Looks like all explorers are down. Try it again later.\n\n" return response
def publish(bot, message, args): logger.info("publish") result = {'fire': False} response = "<u><b>Publish proposal<b><u>\n\n" userInfo = util.crossMessengerSplit(message) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else "Unknown" result['author'] = userName if len(args) != 1: response += messages.proposalIdRequired(bot.messenger, 'publish') elif not util.isInt(args[0].replace('#', '')): response += messages.invalidProposalId(bot.messenger, args[0]) else: proposal = bot.proposals.getProposal(int(args[0].replace('#', ''))) if not proposal: response += messages.proposalNotFound(bot.messenger, args[0]) else: result['proposal'] = proposal twitter = bot.tweeter != None reddit = bot.reddit != None gab = bot.gab != None discord = False telegram = False if 'discord' in bot.messenger: discord = True if 'telegram' in bot.messenger: telegram = True if proposal.published(twitter=twitter, reddit=reddit, gab=gab, discord=discord, telegram=telegram): response += messages.proposalAlreadyPublished( bot.messenger, args[0]) else: result['fire'] = True result['message'] = messages.markdown(response, bot.messenger) return result
def latest(bot): logger.info("latest") response = messages.markdown("<u><b>Latest proposal<b><u>\n\n",bot.messenger) proposal = bot.proposals.getLatestProposals() if proposal: response += messages.proposalDetail(bot.messenger, proposal) else: response += "No latest proposal available!" return response
def remove(bot, message, args): logger.info("remove") response = "<u><b>Remove from watchlist<b><u>\n\n" userInfo = util.crossMessengerSplit(message) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else "Unknown" public = userInfo['public'] dbUser = bot.database.getUser(userId) if not dbUser: logger.error("User not in db?!") response += messages.unexpectedError(bot.messenger) else: if len(args) != 1: response += messages.proposalIdRequired(bot.messenger, 'remove') elif not util.isInt(args[0].replace('#', '')): response += messages.invalidProposalId(bot.messenger, args[0]) else: proposal = bot.proposals.getProposal(int(args[0].replace('#', ''))) if not proposal: response += messages.proposalNotFound(bot.messenger, args[0]) else: currentList = bot.database.getWatchlist(userId=userId) if currentList and len(currentList) and\ not proposal.proposalId in list(map(lambda x: x['proposal_id'],currentList)) or\ not currentList or not len(currentList): response += messages.proposalIsNotOnWatchlist( bot.messenger, proposal.title) else: if bot.database.removeFromWatchlist( userId, proposal.proposalId): response += "Succesfully removed the proposal <b>{}<b> from your watchlist.".format( proposal.title) else: logger.error("Could not remove watchlist entry?!") response += messages.unexpectedError(bot.messenger) return messages.markdown(response, bot.messenger)
def stats(bot): logger.info("stats") response = messages.markdown("<u><b>Statistics<b><u>\n\n", bot.messenger) response += "User: {}\n".format(len(bot.database.getUsers())) response += "Nodes: {}\n".format(len(bot.database.getAllNodes())) response += "90024: {}\n".format( bot.nodeList.getNodeCountForProtocol(90024)) response += "90025: {}\n".format( bot.nodeList.getNodeCountForProtocol(90025)) return response
def stats(bot): logger.info("stats") response = messages.markdown("<u><b>Statistics<b><u>\n\n",bot.messenger) users = bot.database.getUsers() subscriptions = bot.database.getSubscriptions() watchlistEntries = bot.database.getWatchlist() response += "User: {}\n".format(len(users)) response += "Subscriptions: {}\n".format(len(subscriptions)) response += "Watchlist entires: {}\n".format(len(watchlistEntries)) return response
def handleUpdatedProposal(bot, updated, proposal): # Create notification response messages! responses = {} changes = [] if 'voteYes' in updated and updated['voteYes']: change = updated['voteYes'] changes.append( "<b>YES<b> votes (SMART) changed from <b>{:,}<b> to <b>{:,}<b>\n". format(round(change['before'], 1), round(change['now'], 1))) if 'voteNo' in updated and updated['voteNo']: change = updated['voteNo'] changes.append( "<b>NO<b> votes (SMART) changed from <b>{:,}<b> to <b>{:,}<b>\n". format(round(change['before'], 1), round(change['now'], 1))) if 'voteAbstain' in updated and updated['voteAbstain']: change = updated['voteAbstain'] changes.append( "<b>ABSTAIN<b> votes (SMART) changed from <b>{:,}<b> to <b>{:,}<b>\n" .format(round(change['before'], 1), round(change['now'], 1))) if 'status' in updated and updated['status']: change = updated['status'] changes.append( "<b>State<b> changed from <b>{}<b> to <b>{}<b>\n".format( change['before'], change['now'])) if 'currentStatus' in updated and updated['currentStatus']: change = updated['currentStatus'] changes.append( "<b>Current result<b> changed from <b>{}<b> to <b>{}<b>\n".format( change['before'], change['now'])) for entry in bot.database.getWatchlist(proposalId=proposal.proposalId): message = "<u><b>Watchlist update!<b><u>\n\n" message += "The proposal <b>{}<b> obtained the following change{}\n\n".format( proposal.title, "s" if len(changes) > 1 else "") for change in changes: message += change responses[entry['user_id']] = messages.markdown(message, bot.messenger) return responses
def payouts(bot, args): logger.info("payouts") response = messages.markdown("<u><b>Payout statistics<b><u>\n\n", bot.messenger) if not bot.rewardList.running: response += "Not initialized yet. Wait a bit..." return response hours = 12 if len(args): try: hours = float(args[0]) except: pass start = time.time() - (hours * 3600) firstReward = bot.rewardList.getNextReward(start) lastReward = bot.rewardList.getLastReward() if not firstReward: response += "Could not fetch the rewards in the given time range!\n" response += "The last available is at block {} from {} ago.".format( lastReward.block, util.secondsToText(time.time() - lastReward.txtime)) return response total = bot.rewardList.getRewardCount(start=start) vChain = bot.rewardList.getRewardCount(start=start, source=0, meta=0) iChain = bot.rewardList.getRewardCount(start=start, meta=1) nList = bot.rewardList.getRewardCount(start=start, source=1) err = bot.rewardList.getRewardCount(start=start, meta=-1) response += "Blocks: {}\n".format(lastReward.block - firstReward.block) response += "RT: {}\n".format( util.secondsToText(lastReward.txtime - firstReward.txtime)) response += "P: {}\n".format(total) response += "V: {}\n".format(vChain) response += "I: {}\n".format(iChain) response += "NL: {}\n".format(nList) response += "ERR: {}\n".format(err) response += "E: {}%".format(round((1 - (nList / total)) * 100, 1)) return response
def proposalList(bot, proposals, title = "", fallback = ""): logger.info("proposalList - " + title) response = "" if title != "": response = messages.markdown("<u><b>{}<b><u>\n\n".format(title),bot.messenger) if len(proposals): for proposal in proposals: response += messages.proposalShort(bot.messenger, proposal) else: response += fallback return response
def lookup(bot, userId, args): response = messages.markdown("<u><b>Node lookup<b><u>\n\n", bot.messenger) if bot.nodeList.synced() and bot.nodeList.lastBlock: if not len(args): response += messages.lookupArgumentRequiredError(bot.messenger) else: errors = [] lookups = [] for arg in args: ip = util.validateIp(arg) if not ip: errors.append(messages.invalidIpError(bot.messenger, arg)) else: dbNode = bot.nodeList.getNodeByIp(ip) if dbNode: result = bot.nodeList.lookup(dbNode['collateral']) if result: lookups.append( messages.lookupResult(bot.messenger, result)) else: errors.append( messages.lookupError(bot.messenger, ip)) else: errors.append( messages.nodeNotInListError(bot.messenger, ip)) for e in errors: response += e for l in lookups: response += l else: response += "*Sorry, the bot is currently not synced with the network. Try it again in few minutes...*" return response
def lookup(bot, userId, args): response = messages.markdown("<u><b>Node lookup<b><u>\n\n", bot.messenger) with bot.nodeList as nodeList: if nodeList.synced() and nodeList.lastBlock: if not len(args): response += messages.lookupArgumentRequiredError(bot.messenger) else: errors = [] lookups = [] for arg in args: ip = util.validateIp(arg) if not ip: errors.append( messages.invalidIpError(bot.messenger, arg)) else: result = nodeList.lookup(ip) if result: lookups.append( messages.lookupResult(bot.messenger, result)) else: errors.append( messages.nodeNotInListError(bot.messenger, ip)) for e in errors: response += e for l in lookups: response += l else: response += messages.notSynced(bot.messenger) return response
def parse(bot, args): message = help() if len(args): ask = " ".join(args) choices = fuzzy.extract(ask,faqs.keys(),limit=2) if choices[0][1] == choices[1][1] or choices[0][1] < 60: log.warning('Invalid fuzzy result {} - {}\n'.format(ask, choices)) message = unknown(ask) else: topic = choices[0][0] message = "<b>" + faqs[topic].question + "<b>\n\n" + faqs[topic].answerCB(bot) return messages.markdown(header + message,bot.messenger)
def balance(self, bot, update): if not self.isGroup(update): failed = None nodes = [] dbUser = self.database.getUser(update.message.chat_id) userNodes = self.database.getAllNodes(update.message.chat_id) if dbUser == None or userNodes == None or len(userNodes) == 0: response = messages.markdown("<u><b>Balances<b><u>\n\n", self.messenger) response += messages.nodesRequired(self.messenger) self.sendMessage(update.message.chat_id, response) return collaterals = list(map(lambda x: x['collateral'], userNodes)) nodes = self.nodeList.getNodes(collaterals) check = self.explorer.balances(nodes) # Needed cause the balanceChecks dict also gets modified from other # threads. self.balanceSem.acquire() if check: self.balanceChecks[check] = update.message.chat_id else: logger.info("Balance check failed instant.") failed = uuid.uuid4() self.balanceChecks[failed] = update.message.chat_id # Needed cause the balanceChecks dict also gets modified from other # threads. self.balanceSem.release() if failed: self.balancesCB(failed, None)
def info(bot, update): logger.info("network") response = messages.markdown("<u><b>SmartNode Network<b><u>\n\n", bot.messenger) if bot.nodeList.synced() and bot.nodeList.lastBlock: bot.nodeList.acquire() lastBlock = bot.nodeList.lastBlock created = bot.nodeList.count() enabled = bot.nodeList.enabled() qualifiedNormal = bot.nodeList.qualifiedNormal qualifiedUpgrade = bot.nodeList.qualifiedUpgrade upgradeModeDuration = bot.nodeList.remainingUpgradeModeDuration protocolRequirement = bot.nodeList.protocolRequirement() protocol90024 = bot.nodeList.count(90024) protocol90025 = bot.nodeList.count(90025) initialWait = bot.nodeList.minimumUptime() if upgradeModeDuration: upgradeModeDuration = util.secondsToText(upgradeModeDuration) bot.nodeList.release() response += messages.networkState(bot.messenger, lastBlock, created, enabled, qualifiedNormal, qualifiedUpgrade, upgradeModeDuration, protocolRequirement, protocol90024, protocol90025, util.secondsToText(initialWait)) else: response += "*Sorry, the bot is currently not synced with the network. Try it again in few minutes...*" return response
def new(bot): logger.info("new") twitter = bot.tweeter != None reddit = bot.reddit != None gab = bot.gab != None discord = False telegram = False if 'discord' in bot.messenger: discord = True if 'telegram' in bot.messenger: telegram = True proposals = bot.proposals.getNotPublishedProposals(twitter=twitter, reddit=reddit, gab=gab, discord=discord, telegram=telegram) response = "<u><b>Unpublished proposals<b><u>\n\n" if len(proposals): for proposal in proposals: response += messages.proposalNew(bot.messenger, proposal, twitter=twitter, reddit=reddit, gab=gab, discord=discord, telegram=telegram) else: response += "Currently no proposal ready to publish!" return messages.markdown(response, bot.messenger)
def subscription(bot, message, state): logger.info("subscription") response = "<u><b>Subscription<b><u>\n\n" userInfo = util.crossMessengerSplit(message) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else "Unknown" public = userInfo['public'] dbUser = bot.database.getUser(userId) if not dbUser: logger.error("User not in db?!") response += messages.unexpectedError(bot.messenger) else: logger.info("subscription - update {}".format(state)) bot.database.updateSubscription(userId, state) response += "Succesfully <b>{}subscribed<b> new/ended proposals.".format("" if state else "un") return messages.markdown(response, bot.messenger)
def top(bot, update, args): response = "<u><b>Top nodes<b><u>\n\n" userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else None logger.debug("nodes - user: {}".format(userId)) nodesFound = False user = bot.database.getUser(userId) userNodes = bot.database.getAllNodes(userId) if user == None or userNodes == None or len(userNodes) == 0: response += messages.nodesRequired(bot.messenger) else: invalidFilterValueMsg = "<b>ERROR<b>: Invalid filter value: <b>{}<b>! Valid range: 10 - 100\n\n" topPercent = 10 if len(args) >= 1: if util.isInt(args[0]) and\ int(args[0]) >= 10 and int(args[0]) <= 100: topPercent = int(args[0]) else: response += invalidFilterValueMsg.format( messages.removeMarkdown(args[0])) response += "<b>Filter<b> {}%\n\n".format(topPercent) with bot.nodeList as nodeList: topX = nodeList.enabledWithMinProtocol() * (topPercent / 100) collaterals = list(map(lambda x: x['collateral'], userNodes)) nodes = nodeList.getNodes(collaterals) topNodes = list( filter(lambda x: x.position <= topX and x.position > 0, nodes)) minimumUptime = nodeList.minimumUptime() if len(topNodes): for masternode in sorted(topNodes, key=lambda x: x.position if x.position > 0 else 100000): userNode = bot.database.getNodes(masternode.collateral, user['id']) response += "<b>" + userNode['name'] + "<b>" response += "\nPosition " + messages.markdown( masternode.positionString(minimumUptime), bot.messenger) response += "\n" + messages.link( bot.messenger, 'https://explorer3.curium.cc/address/{}'.format( masternode.payee), 'Open the explorer!') response += "\n\n" else: response += "<b>You have currently no nodes in the top {}% of the queue.<b>\n\n".format( topPercent) return messages.markdown(response, bot.messenger)
def nodeAdd(bot, update, args): userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else None response = messages.markdown("<u><b>Add<b><u>\n\n", bot.messenger) logger.debug("add - " + " ".join(args)) logger.debug("add - user: {}".format(userId)) if len(args) == 0: response += messages.markdown(( "<b>ERROR<b>: Arguments required: <b>IPAddress_0;name_0 ... IPAddress_n;name_n<b>\n\n" "Example: <cb>add<ca> 43.121.56.87;Node1 56.76.27.100;Node2\n"), bot.messenger) valid = False else: with bot.nodeList as nodeList: for arg in args: valid = True newNode = arg.split(";") if len(newNode) != 2: response += messages.invalidParameterError( bot.messenger, arg) valid = False else: ip = util.validateIp(newNode[0]) name = util.validateName(newNode[1]) if not ip: response += messages.invalidIpError( bot.messenger, newNode[0]) valid = False if not name: response += messages.invalidNameError( bot.messenger, newNode[1]) valid = False if valid: node = nodeList.getNodeByIp(ip) if node == None: response += messages.nodeNotInListError( bot.messenger, ip) else: if bot.database.addNode(node.collateral, name, userId, userName): response += "Added node {}!\n".format(ip) else: response += messages.nodeExistsError( bot.messenger, ip) return response
def history(bot, update): response = "<u><b>History<b><u>\n\n" userInfo = util.crossMessengerSplit(update) userId = userInfo['user'] if 'user' in userInfo else None userName = userInfo['name'] if 'name' in userInfo else None logger.debug("history - user: {}".format(userId)) nodesFound = False user = bot.database.getUser(userId) userNodes = bot.database.getAllNodes(userId) if user == None or userNodes == None or len(userNodes) == 0: response += messages.nodesRequired(bot.messenger) else: with bot.nodeList as nodeList: collaterals = list(map(lambda x: x['collateral'], userNodes)) nodes = nodeList.getNodes(collaterals) time30Days = time.time() - (2592000) # now - 30d * 24h * 60m * 60s totalInvest = len(nodes) * 10000 totalProfit = 0 totalAvgInterval = 0 totalFirst = 0 countMultiplePayouts = 0 totalProfit30Days = 0 for masternode in nodes: userNode = bot.database.getNodes(masternode.collateral, user['id']) rewards = bot.rewardList.getRewardsForPayee(masternode.payee) profit = sum(map(lambda x: x.amount, rewards)) profit30Days = sum( map(lambda x: x.amount if x.txtime > time30Days else 0, rewards)) totalProfit30Days += profit30Days totalProfit += round(profit, 1) avgInterval = 0 masterPerDay = 0 first = 0 last = 0 if len(rewards) == 1: first = rewards[0].txtime if len(rewards) > 1: countMultiplePayouts += 1 payoutTimes = list(map(lambda x: x.txtime, rewards)) first = min(payoutTimes) last = max(payoutTimes) if not totalFirst or first and totalFirst > first: totalFirst = first if last: avgInterval = (last - first) / len(rewards) totalAvgInterval += avgInterval masterPerDay = round( profit / ((time.time() - first) / 86400), 1) response += "<u><b>Node - " + userNode['name'] + "<b><u>\n\n" response += "<b>Payouts<b> {}\n".format(len(rewards)) response += "<b>Profit<b> {:,} CRU\n".format(round(profit, 1)) response += "<b>Profit (30 days)<b> {:,} CRU\n".format( round(profit30Days, 1)) if avgInterval: response += "\n<b>Payout interval<b> " + util.secondsToText( avgInterval) if masterPerDay: response += "\n<b>CRU/day<b> {:,} CRU".format(masterPerDay) response += "\n<b>ROI (CRU)<b> {}%".format( round((profit / 10000.0) * 100.0, 1)) response += "\n\n" response += "<u><b>Total stats<b><u>\n\n" if totalFirst: response += "<b>First payout<b> {} ago\n\n".format( util.secondsToText(time.time() - totalFirst)) response += "<b>Profit (30 days)<b> {:,} CRU\n".format( round(totalProfit30Days, 1)) response += "<b>CRU/day (30 days)<b> {:,} CRU\n\n".format( round(totalProfit30Days / 30, 1)) if totalAvgInterval: totalAvgInterval = totalAvgInterval / countMultiplePayouts response += "<b>Total payout interval<b> {}\n".format( util.secondsToText(totalAvgInterval)) response += "<b>Total CRU/day<b> {:,} CRU\n\n".format( round(totalProfit / ((time.time() - totalFirst) / 86400), 1)) response += "<b>Total profit<b> {:,} CRU\n".format( round(totalProfit, 1)) response += "<b>Total ROI (CRU)<b> {}%\n\n".format( round((totalProfit / totalInvest) * 100, 1)) return messages.markdown(response, bot.messenger)