def post_stats(post): """Get post statistics and derived properties. Source: contentStats - https://github.com/steemit/condenser/blob/master/src/app/utils/StateFunctions.js#L109 """ neg_rshares = 0 total_votes = 0 up_votes = 0 for vote in post['active_votes']: rshares = int(vote['rshares']) if rshares == 0: continue total_votes += 1 if rshares > 0: up_votes += 1 if rshares < 0: neg_rshares += rshares # take negative rshares, divide by 2, truncate 10 digits (plus neg sign), # and count digits. creates a cheap log10, stake-based flag weight. # result: 1 = approx $400 of downvoting stake; 2 = $4,000; etc flag_weight = max((len(str(int(neg_rshares / 2))) - 11, 0)) author_rep = rep_log10(post['author_reputation']) has_pending_payout = sbd_amount(post['pending_payout_value']) >= 0.02 return { 'hide': author_rep < 0 and not has_pending_payout, 'gray': author_rep < 1, 'author_rep': author_rep, 'flag_weight': flag_weight, 'total_votes': total_votes, 'up_votes': up_votes }
def _sql(cls, account, cached_at): """Prepare a SQL query from a steemd account.""" vests = vests_amount(account['vesting_shares']) vote_weight = (vests + vests_amount(account['received_vesting_shares']) - vests_amount(account['delegated_vesting_shares'])) proxy_weight = 0 if account['proxy'] else float(vests) for satoshis in account['proxied_vsf_votes']: proxy_weight += float(satoshis) / 1e6 # remove empty keys useless = ['transfer_history', 'market_history', 'post_history', 'vote_history', 'other_history', 'tags_usage', 'guest_bloggers'] for key in useless: del account[key] # pull out valid profile md and delete the key profile = safe_profile_metadata(account) del account['json_metadata'] del account['posting_json_metadata'] active_at = max(account['created'], account['last_account_update'], account['last_post'], account['last_root_post'], account['last_vote_time']) values = { 'name': account['name'], 'created_at': account['created'], 'proxy': account['proxy'], 'post_count': account['post_count'], 'reputation': rep_log10(account['reputation']), 'proxy_weight': proxy_weight, 'vote_weight': vote_weight, 'active_at': active_at, 'cached_at': cached_at, 'display_name': profile['name'], 'about': profile['about'], 'location': profile['location'], 'website': profile['website'], 'profile_image': profile['profile_image'], 'cover_image': profile['cover_image'], 'raw_json': json.dumps(account)} # update rank field, if present _id = cls.get_id(account['name']) if _id in cls._ranks: values['rank'] = cls._ranks[_id] bind = ', '.join([k+" = :"+k for k in list(values.keys())][1:]) return ("UPDATE hive_accounts SET %s WHERE name = :name" % bind, values)
def _generate_cache_sqls(cls, accounts): """Prepare a SQL query from a steemd account.""" cached_at = datetime.now().strftime('%Y-%m-%dT%H:%M:%S') sqls = [] for account in SteemClient.instance().get_accounts(accounts): vote_weight = (vests_amount(account['vesting_shares']) + vests_amount(account['received_vesting_shares']) - vests_amount(account['delegated_vesting_shares'])) # remove empty keys useless = [ 'transfer_history', 'market_history', 'post_history', 'vote_history', 'other_history', 'tags_usage', 'guest_bloggers' ] for key in useless: del account[key] # pull out valid profile md and delete the key profile = safe_profile_metadata(account) del account['json_metadata'] values = { 'name': account['name'], 'proxy': account['proxy'], 'post_count': account['post_count'], 'reputation': rep_log10(account['reputation']), 'proxy_weight': vests_amount(account['vesting_shares']), 'vote_weight': vote_weight, 'kb_used': int(account['lifetime_bandwidth']) / 1e6 / 1024, 'active_at': account['last_bandwidth_update'], 'cached_at': cached_at, 'display_name': profile['name'], 'about': profile['about'], 'location': profile['location'], 'website': profile['website'], 'profile_image': profile['profile_image'], 'cover_image': profile['cover_image'], 'raw_json': json.dumps(account) } update = ', '.join([k + " = :" + k for k in list(values.keys())][1:]) sql = "UPDATE hive_accounts SET %s WHERE name = :name" % (update) sqls.append((sql, values)) return sqls
def _bridge_profile_object(row): """Convert an internal account record into legacy-steemd style.""" #Important. The member `sp` in `stats` is removed, because currently the hivemind doesn't hold any balances. # The member `vote_weight` from `hive_accounts` is removed as well. profile = safe_db_profile_metadata(row['posting_json_metadata'], row['json_metadata']) return { 'id': row['id'], 'name': row['name'], 'created': json_date(row['created_at']), 'active': json_date(row['active_at']), 'post_count': row['post_count'], 'reputation': rep_log10(row['reputation']), 'blacklists': [], 'stats': { 'rank': row['rank'], 'following': row['following'], 'followers': row['followers'], }, 'metadata': { 'profile': { 'name': profile['name'], 'about': profile['about'], 'website': profile['website'], 'location': profile['location'], 'cover_image': profile['cover_image'], 'profile_image': profile['profile_image'], 'blacklist_description': profile['blacklist_description'] if 'blacklist_description' in profile else '', 'muted_list_description': profile['muted_list_description'] if 'muted_list_description' in profile else '' } } }
def post_stats(post): """Get post statistics and derived properties. Source: contentStats - https://github.com/steemit/condenser/blob/master/src/app/utils/StateFunctions.js#L109 """ net_rshares_adj = 0 neg_rshares = 0 total_votes = 0 up_votes = 0 for vote in post['active_votes']: if vote['percent'] == 0: continue total_votes += 1 rshares = int(vote['rshares']) sign = 1 if vote['percent'] > 0 else -1 if sign > 0: up_votes += 1 if sign < 0: neg_rshares += rshares # For graying: sum rshares, but ignore neg rep users and dust downvotes neg_rep = str(vote['reputation'])[0] == '-' if not (neg_rep and sign < 0 and len(str(rshares)) < 11): net_rshares_adj += rshares # take negative rshares, divide by 2, truncate 10 digits (plus neg sign), # and count digits. creates a cheap log10, stake-based flag weight. # result: 1 = approx $400 of downvoting stake; 2 = $4,000; etc flag_weight = max((len(str(neg_rshares / 2)) - 11, 0)) author_rep = rep_log10(post['author_reputation']) is_low_value = net_rshares_adj < -9999999999 has_pending_payout = sbd_amount(post['pending_payout_value']) >= 0.02 return { 'hide': not has_pending_payout and (author_rep < 0), 'gray': not has_pending_payout and (author_rep < 1 or is_low_value), 'author_rep': author_rep, 'flag_weight': flag_weight, 'total_votes': total_votes, 'up_votes': up_votes }
def _sql(cls, account, cached_at): """Prepare a SQL query from a steemd account.""" vote_weight = (vests_amount(account['vesting_shares']) + vests_amount(account['received_vesting_shares']) - vests_amount(account['delegated_vesting_shares'])) # remove empty keys useless = [ 'transfer_history', 'market_history', 'post_history', 'vote_history', 'other_history', 'tags_usage', 'guest_bloggers' ] for key in useless: del account[key] # pull out valid profile md and delete the key profile = safe_profile_metadata(account) del account['json_metadata'] active_at = max(account['created'], account['last_post'], account['last_vote_time']) values = { 'name': account['name'], 'created_at': account['created'], 'proxy': account['proxy'], 'post_count': account['post_count'], 'reputation': rep_log10(account['reputation']), 'proxy_weight': vests_amount(account['vesting_shares']), 'vote_weight': vote_weight, 'active_at': active_at, 'cached_at': cached_at, 'display_name': profile['name'], 'about': profile['about'], 'location': profile['location'], 'website': profile['website'], 'profile_image': profile['profile_image'], 'cover_image': profile['cover_image'], 'raw_json': json.dumps(account) } bind = ', '.join([k + " = :" + k for k in list(values.keys())][1:]) return ("UPDATE hive_accounts SET %s WHERE name = :name" % bind, values)
def _bridge_post_object(row, truncate_body=0): """Given a hive_posts row, create a legacy-style post object.""" paid = row['is_paidout'] post = {} post['post_id'] = row['id'] post['author'] = row['author'] post['permlink'] = row['permlink'] post['category'] = row.get('category', 'undefined') post['title'] = row['title'] post['body'] = row['body'][0:truncate_body] if truncate_body else row[ 'body'] try: post['json_metadata'] = json.loads(row['json']) except Exception: post['json_metadata'] = {} post['created'] = json_date(row['created_at']) post['updated'] = json_date(row['updated_at']) post['depth'] = row['depth'] post['children'] = row['children'] post['net_rshares'] = row['rshares'] post['is_paidout'] = row['is_paidout'] post['payout_at'] = json_date(row['payout_at']) post['payout'] = float(row['payout'] + row['pending_payout']) post['pending_payout_value'] = _amount(0 if paid else post['payout']) post['author_payout_value'] = _amount(0) # supplemented below post['curator_payout_value'] = _amount(0) # supplemented below post['promoted'] = _amount(row['promoted']) post['replies'] = [] post['author_reputation'] = rep_log10(row['author_rep']) neg_rshares = (row['rshares'] - row['abs_rshares'] ) // 2 # effectively sum of all negative rshares # take negative rshares, divide by 2, truncate 10 digits (plus neg sign), # and count digits. creates a cheap log10, stake-based flag weight. # result: 1 = approx $400 of downvoting stake; 2 = $4,000; etc flag_weight = max((len(str(int(neg_rshares / 2))) - 11, 0)) post['stats'] = { 'hide': row['is_hidden'], 'gray': row['is_grayed'], 'total_votes': row['total_votes'], 'flag_weight': float(flag_weight) } # TODO: down_weight #post['author_reputation'] = rep_to_raw(row['author_rep']) post['url'] = row['url'] post['beneficiaries'] = row['beneficiaries'] post['max_accepted_payout'] = row['max_accepted_payout'] post['percent_hbd'] = row['percent_hbd'] if paid: curator_payout = sbd_amount(row['curator_payout_value']) post['author_payout_value'] = _amount(row['payout'] - curator_payout) post['curator_payout_value'] = _amount(curator_payout) # TODO: re-evaluate if row['depth'] > 0: post['parent_author'] = row['parent_author'] post['parent_permlink'] = row['parent_permlink_or_category'] post['title'] = 'RE: ' + row[ 'root_title'] # PostSummary & comment context return post
def test_rep_log10(): assert rep_log10(0) == 25 assert rep_log10('2321387987213') == 55.29
def _vote_csv_row(vote): """Convert a vote object into minimal CSV line.""" rep = rep_log10(vote['reputation']) return "%s,%s,%s,%s" % (vote['voter'], vote['rshares'], vote['percent'], rep)
def _vote_csv_row(vote): rep = rep_log10(vote['reputation']) return "%s,%s,%s,%s" % (vote['voter'], vote['rshares'], vote['percent'], rep)