def _condenser_profile_object(row): """Convert an internal account record into legacy-steemd style.""" blacklists = Mutes.lists(row['name'], row['reputation']) 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': row['reputation'], 'blacklists': blacklists, 'stats': { 'sp': int(row['vote_weight'] * 0.0005037), 'rank': row['rank'], 'following': row['following'], 'followers': row['followers'], }, 'metadata': { 'profile': { 'name': row['display_name'], 'about': row['about'], 'website': row['website'], 'location': row['location'], 'cover_image': row['cover_image'], 'profile_image': row['profile_image'], } } }
def database_post_object(row, truncate_body=0): """Given a hive_posts row, create a legacy-style post object.""" paid = row['is_paidout'] post = {} post['author_rewards'] = row['author_rewards'] post['id'] = row['id'] post['author'] = row['author'] post['permlink'] = row['permlink'] post['category'] = row['category'] if 'category' in row else 'undefined' post['title'] = row['title'] post['body'] = row['body'][0:truncate_body] if truncate_body else row['body'] post['json_metadata'] = row['json'] post['created'] = json_date(row['created_at']) post['last_update'] = json_date(row['updated_at']) post['depth'] = row['depth'] post['children'] = row['children'] post['last_payout'] = json_date(row['last_payout_at']) post['cashout_time'] = json_date(row['cashout_time']) post['max_cashout_time'] = json_date(None) # ABW: only relevant up to HF17, timestamp::max for all posts later (and also all paid) curator_payout = sbd_amount(row['curator_payout_value']) post['curator_payout_value'] = to_nai(_amount(curator_payout)) post['total_payout_value'] = to_nai(_amount(row['payout'] - curator_payout)) post['reward_weight'] = 10000 # ABW: only relevant between HF12 and HF17 and we don't have access to correct value post['root_author'] = row['root_author'] post['root_permlink'] = row['root_permlink'] post['allow_replies'] = row['allow_replies'] post['allow_votes'] = row['allow_votes'] post['allow_curation_rewards'] = row['allow_curation_rewards'] post['parent_author'] = row['parent_author'] post['parent_permlink'] = row['parent_permlink_or_category'] post['beneficiaries'] = row['beneficiaries'] post['max_accepted_payout'] = to_nai(row['max_accepted_payout']) post['percent_hbd'] = row['percent_hbd'] post['net_votes'] = row['net_votes'] if paid: post['total_vote_weight'] = 0 post['vote_rshares'] = 0 post['net_rshares'] = 0 # if row['rshares'] > 0 else row['rshares'] ABW: used to be like this but after HF19 cashouts disappear and all give 0 post['abs_rshares'] = 0 post['children_abs_rshares'] = 0 else: post['total_vote_weight'] = row['total_vote_weight'] post['vote_rshares'] = ( row['rshares'] + row['abs_rshares'] ) // 2 # effectively sum of all positive rshares post['net_rshares'] = row['rshares'] post['abs_rshares'] = row['abs_rshares'] post['children_abs_rshares'] = 0 # TODO - ABW: I'm not sure about that, it is costly and useless (used to be part of mechanism to determine cashout time) return post
def api_vote_info(rows, votes_presentation): ret = [] for row in rows: if votes_presentation == VotesPresentation.DatabaseApi: ret.append( dict(id=row.id, voter=row.voter, author=row.author, permlink=row.permlink, weight=row.weight, rshares=row.rshares, vote_percent=row.percent, last_update=json_date(row.last_update), num_changes=row.num_changes)) elif votes_presentation == VotesPresentation.CondenserApi: ret.append( dict(percent=str(row.percent), reputation=row.reputation, rshares=row.rshares, voter=row.voter)) elif votes_presentation == VotesPresentation.BridgeApi: ret.append(dict(rshares=row.rshares, voter=row.voter)) else: ret.append( dict(percent=row.percent, reputation=row.reputation, rshares=row.rshares, time=json_date(row.last_update), voter=row.voter, weight=row.weight)) return ret
async def list_subscribers(context, community, last='', limit=100): """Lists subscribers of `community`.""" community = valid_community(community) last = valid_account(last, True) limit = valid_limit(limit, 100, 100) db = context['db'] sql = "SELECT * FROM bridge_list_subscribers( (:community)::VARCHAR, (:last)::VARCHAR, (:limit)::INT )" rows = await db.query_all(sql, community=community, last=last, limit=limit) return [(r[0], r[1], r[2], json_date(r[3])) for r in rows]
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 _render(row): """Convert object to string rep.""" # src dst payload community post out = { 'id': row['id'], 'type': NotifyType(row['type_id']).name, 'score': row['score'], 'date': json_date(row['created_at']), 'msg': _render_msg(row), 'url': _render_url(row), } #if row['community']: # out['community'] = (row['community'], row['community_title']) return out
async def get_blog(context, account: str, start_entry_id: int = 0, limit: int = None): """Get posts for an author's blog (w/ reblogs), paged by index/limit. Equivalent to get_discussions_by_blog, but uses offset-based pagination. Examples: (ABW: old description and examples were misleading as in many cases code worked differently, also now more cases actually work that gave error earlier) (acct, -1, limit) for limit 1..500 - returns latest (no more than) limit posts (acct, 0) - returns latest single post (ABW: this is a bug but I left it here because I'm afraid it was actively used - it should return oldest post) (acct, 0, limit) for limit 1..500 - same as (acct, -1, limit) - see above (acct, last_idx) for positive last_idx - returns last_idx oldest posts, or posts in range [last_idx..last_idx-500) when last_idx >= 500 (acct, last_idx, limit) for positive last_idx and limit 1..500 - returns posts in range [last_idx..last_idx-limit) """ db = context['db'] account = valid_account(account) if not start_entry_id: start_entry_id = -1 start_entry_id = valid_offset(start_entry_id) if not limit: limit = max(start_entry_id + 1, 1) limit = min(limit, 500) limit = valid_limit(limit, 500, None) sql = "SELECT * FROM condenser_get_blog(:account, :last, :limit)" result = await db.query_all(sql, account=account, last=start_entry_id, limit=limit) out = [] for row in result: row = dict(row) post = _condenser_post_object(row) post['active_votes'] = await find_votes_impl( db, row['author'], row['permlink'], VotesPresentation.CondenserApi) out.append({ "blog": account, "entry_id": row['entry_id'], "comment": post, "reblogged_on": json_date(row['reblogged_at']) }) return list(reversed(out))
async def get_relationship_between_accounts(context, account1, account2, observer=None, debug=None): valid_account(account1) valid_account(account2) db = context['db'] sql = "SELECT * FROM bridge_get_relationship_between_accounts( (:account1)::VARCHAR, (:account2)::VARCHAR )" sql_result = await db.query_row(sql, account1=account1, account2=account2) result = { 'follows': False, 'ignores': False, 'blacklists': False, 'follows_blacklists': False, 'follows_muted': False } row = dict(sql_result) state = row['state'] if state == 1: result['follows'] = True elif state == 2: result['ignores'] = True if row['blacklisted']: result['blacklists'] = True if row['follow_blacklists']: result['follows_blacklists'] = True if row['follow_muted']: result['follows_muted'] = True if isinstance(debug, bool) and debug: # result['id'] = row['id'] # ABW: it just made tests harder as any change could trigger id changes # data below is sufficient to see when record was created and updated result['created_at'] = json_date(row['created_at']) if row['created_at'] else None result['block_num'] = row['block_num'] return result
async def get_blog_entries(context, account: str, start_entry_id: int = 0, limit: int = None): """Get 'entries' for an author's blog (w/ reblogs), paged by index/limit. Interface identical to get_blog, but returns minimalistic post references. """ db = context['db'] account = valid_account(account) if not start_entry_id: start_entry_id = -1 start_entry_id = valid_offset(start_entry_id) if not limit: limit = max(start_entry_id + 1, 1) limit = min(limit, 500) limit = valid_limit(limit, 500, None) sql = "SELECT * FROM condenser_get_blog_entries(:account, :last, :limit)" result = await db.query_all(sql, account=account, last=start_entry_id, limit=limit) out = [] for row in result: row = dict(row) out.append({ "blog": account, "entry_id": row['entry_id'], "author": row['author'], "permlink": row['permlink'], "reblogged_on": json_date(row['reblogged_at']) }) return list(reversed(out))
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 _condenser_post_object(row, truncate_body=0): """Given a hive_posts_cache row, create a legacy-style post object.""" paid = row['is_paidout'] # condenser#3424 mitigation if not row['category']: row['category'] = 'undefined' post = {} post['post_id'] = row['post_id'] post['author'] = row['author'] post['permlink'] = row['permlink'] post['category'] = row['category'] post['title'] = row['title'] post['body'] = row['body'][0:truncate_body] if truncate_body else row[ 'body'] post['json_metadata'] = json.loads(row['json']) 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']) post['pending_payout_value'] = _amount(0 if paid else row['payout']) post['author_payout_value'] = _amount(row['payout'] if paid else 0) post['curator_payout_value'] = _amount(0) post['promoted'] = _amount(row['promoted']) post['replies'] = [] post['active_votes'] = _hydrate_active_votes(row['votes']) post['author_reputation'] = row['author_rep'] post['stats'] = { 'hide': row['is_hidden'], 'gray': row['is_grayed'], 'total_votes': row['total_votes'], 'flag_weight': row['flag_weight'] } # import fields from legacy object assert row['raw_json'] assert len(row['raw_json']) > 32 raw_json = json.loads(row['raw_json']) # TODO: move to core, or payout_details post['beneficiaries'] = raw_json['beneficiaries'] post['max_accepted_payout'] = raw_json['max_accepted_payout'] post['percent_steem_dollars'] = raw_json[ 'percent_steem_dollars'] # TODO: systag? if paid: curator_payout = sbd_amount(raw_json['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'] = raw_json['parent_author'] post['parent_permlink'] = raw_json['parent_permlink'] post['title'] = 'RE: ' + raw_json[ 'root_title'] # PostSummary & comment context #else: # post['parent_author'] = '' # post['parent_permlink'] = '' post['url'] = raw_json['url'] return post
def _condenser_post_object(row, truncate_body=0): """Given a hive_posts_cache row, create a legacy-style post object.""" paid = row['is_paidout'] # condenser#3424 mitigation if not row['category']: row['category'] = 'undefined' post = {} post['post_id'] = row['post_id'] post['author'] = row['author'] post['permlink'] = row['permlink'] post['category'] = row['category'] post['title'] = row['title'] post['body'] = row['body'][0:truncate_body] if truncate_body else row[ 'body'] post['json_metadata'] = row['json'] post['created'] = json_date(row['created_at']) post['last_update'] = json_date(row['updated_at']) post['depth'] = row['depth'] post['children'] = row['children'] post['net_rshares'] = row['rshares'] post['last_payout'] = json_date(row['payout_at'] if paid else None) post['cashout_time'] = json_date(None if paid else row['payout_at']) post['total_payout_value'] = _amount(row['payout'] if paid else 0) post['curator_payout_value'] = _amount(0) post['pending_payout_value'] = _amount(0 if paid else row['payout']) post['promoted'] = "%.3f SBD" % row['promoted'] post['replies'] = [] post['body_length'] = len(row['body']) post['active_votes'] = _hydrate_active_votes(row['votes']) post['author_reputation'] = rep_to_raw(row['author_rep']) # import fields from legacy object assert row['raw_json'] assert len(row['raw_json']) > 32 raw_json = json.loads(row['raw_json']) if row['depth'] > 0: post['parent_author'] = raw_json['parent_author'] post['parent_permlink'] = raw_json['parent_permlink'] else: post['parent_author'] = '' post['parent_permlink'] = row['category'] post['url'] = raw_json['url'] post['root_title'] = raw_json['root_title'] post['beneficiaries'] = raw_json['beneficiaries'] post['max_accepted_payout'] = raw_json['max_accepted_payout'] post['percent_steem_dollars'] = raw_json['percent_steem_dollars'] if paid: curator_payout = sbd_amount(raw_json['curator_payout_value']) post['curator_payout_value'] = _amount(curator_payout) post['total_payout_value'] = _amount(row['payout'] - curator_payout) # not used by condenser, but may be useful #post['net_votes'] = post['total_votes'] - row['up_votes'] #post['allow_replies'] = raw_json['allow_replies'] #post['allow_votes'] = raw_json['allow_votes'] #post['allow_curation_rewards'] = raw_json['allow_curation_rewards'] return post
def _condenser_post_object(row, truncate_body=0, get_content_additions=False): """Given a hive_posts row, create a legacy-style post object.""" paid = row['is_paidout'] full_payout = row['pending_payout'] + row['payout'] post = {} post['author'] = row['author'] post['permlink'] = row['permlink'] if not row['category']: post['category'] = 'undefined' # condenser#3424 mitigation else: post['category'] = row['category'] post['title'] = row['title'] post['body'] = row['body'][0:truncate_body] if truncate_body else row[ 'body'] post['json_metadata'] = row['json'] post['created'] = json_date(row['created_at']) post['last_update'] = json_date(row['updated_at']) post['depth'] = row['depth'] post['children'] = row['children'] post['last_payout'] = json_date(row['payout_at'] if paid else None) post['cashout_time'] = json_date(None if paid else row['payout_at']) post['total_payout_value'] = _amount(row['payout'] if paid else 0) post['curator_payout_value'] = _amount(0) post['pending_payout_value'] = _amount(0 if paid else full_payout) post['promoted'] = _amount(row['promoted']) post['replies'] = [] post['body_length'] = len(row['body']) post['author_reputation'] = row['author_rep'] post['parent_author'] = row['parent_author'] post['parent_permlink'] = row['parent_permlink_or_category'] post['url'] = row['url'] post['root_title'] = row['root_title'] post['beneficiaries'] = row['beneficiaries'] post['max_accepted_payout'] = row['max_accepted_payout'] post['percent_hbd'] = row['percent_hbd'] if get_content_additions: post['id'] = row[ 'id'] # let's be compatible with old code until this API is supported. post['author_rewards'] = row['author_rewards'] post['max_cashout_time'] = json_date( None ) # ABW: only relevant up to HF17, timestamp::max for all posts later (and also all paid) curator_payout = sbd_amount(row['curator_payout_value']) post['curator_payout_value'] = _amount(curator_payout) post['total_payout_value'] = _amount(row['payout'] - curator_payout) post['reward_weight'] = 10000 post['root_author'] = row['root_author'] post['root_permlink'] = row['root_permlink'] post['allow_replies'] = row['allow_replies'] post['allow_votes'] = row['allow_votes'] post['allow_curation_rewards'] = row['allow_curation_rewards'] post['reblogged_by'] = [] post['net_votes'] = row['net_votes'] post[ 'children_abs_rshares'] = 0 # see: hive/server/database_api/objects.py:68 post['total_pending_payout_value'] = '0.000 HBD' # no data if paid: post['total_vote_weight'] = 0 post['vote_rshares'] = 0 post['net_rshares'] = 0 post['abs_rshares'] = 0 else: post['total_vote_weight'] = row['total_vote_weight'] post['vote_rshares'] = (row['rshares'] + row['abs_rshares']) // 2 post['net_rshares'] = row['rshares'] post['abs_rshares'] = row['abs_rshares'] else: post['post_id'] = row['id'] post['net_rshares'] = row['rshares'] if paid: curator_payout = sbd_amount(row['curator_payout_value']) post['curator_payout_value'] = _amount(curator_payout) post['total_payout_value'] = _amount(row['payout'] - curator_payout) return post