Beispiel #1
0
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'],
            }
        }
    }
Beispiel #2
0
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
Beispiel #3
0
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
Beispiel #4
0
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]
Beispiel #5
0
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 ''
            }
        }
    }
Beispiel #6
0
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
Beispiel #7
0
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))
Beispiel #8
0
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
Beispiel #9
0
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))
Beispiel #10
0
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
Beispiel #11
0
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
Beispiel #12
0
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
Beispiel #13
0
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