예제 #1
0
async def _get_account_discussion_by_key(account, key):
    assert account, 'account must be specified'
    assert key, 'discussion key must be specified'

    if key == 'recent_replies':
        posts = load_posts(cursor.pids_by_replies_to_account(account, '', 20))
    elif key == 'comments':
        posts = load_posts(cursor.pids_by_account_comments(account, '', 20))
    elif key == 'blog':
        posts = load_posts(cursor.pids_by_blog(account, '', '', 20))
    elif key == 'feed':
        res = cursor.pids_by_feed_with_reblog(account, '', '', 20)
        posts = load_posts_reblogs(res)
    else:
        raise ApiError("unknown account discussion key %s" % key)

    return posts
예제 #2
0
async def get_account_votes(context, account):
    """Return an info message about get_acccount_votes being unsupported."""
    # pylint: disable=unused-argument
    raise ApiError(
        "get_account_votes is no longer supported, for details see "
        "https://steemit.com/steemit/@steemitdev/additional-public-api-change")
예제 #3
0
async def get_state(context, path: str):
    """`get_state` reimplementation.

    See: https://github.com/steemit/steem/blob/06e67bd4aea73391123eca99e1a22a8612b0c47e/libraries/app/database_api.cpp#L1937
    """
    (path, part) = _normalize_path(path)

    db = context['db']

    state = {
        'feed_price': await _get_feed_price(db),
        'props': await _get_props_lite(db),
        'tags': {},
        'accounts': {},
        'content': {},
        'tag_idx': {
            'trending': []
        },
        'discussion_idx': {
            "": {}
        }
    }

    # account - `/@account/tab` (feed, blog, comments, replies)
    if part[0] and part[0][0] == '@':
        assert not part[1] == 'transfers', 'transfers API not served here'
        assert not part[2], 'unexpected account path[2] %s' % path

        if part[1] == '':
            part[1] = 'blog'

        account = valid_account(part[0][1:])
        state['accounts'][account] = await _load_account(db, account)

        if part[1] in ACCOUNT_TAB_KEYS:
            key = ACCOUNT_TAB_KEYS[part[1]]
            posts = await _get_account_discussion_by_key(db, account, key)
            state['content'] = _keyed_posts(posts)
            state['accounts'][account][key] = list(state['content'].keys())
        elif part[1] in ACCOUNT_TAB_IGNORE:
            pass  # condenser no-op URLs
        else:
            # invalid/undefined case; probably requesting `@user/permlink`,
            # but condenser still relies on a valid response for redirect.
            state['error'] = 'invalid get_state account path %s' % path

    # discussion - `/category/@account/permlink`
    elif part[1] and part[1][0] == '@':
        author = valid_account(part[1][1:])
        permlink = valid_permlink(part[2])
        state['content'] = await _load_discussion(db, author, permlink)
        state['accounts'] = await _load_content_accounts(db, state['content'])

    # ranked posts - `/sort/category`
    elif part[0] in POST_LIST_SORTS:
        assert not part[2], "unexpected discussion path part[2] %s" % path
        sort = valid_sort(part[0])
        tag = valid_tag(part[1].lower(), allow_empty=True)
        pids = await cursor.pids_by_query(db, sort, '', '', 20, tag)
        state['content'] = _keyed_posts(await load_posts(db, pids))
        state['discussion_idx'] = {tag: {sort: list(state['content'].keys())}}
        state['tag_idx'] = {
            'trending': await get_top_trending_tags_summary(context)
        }

    # tag "explorer" - `/tags`
    elif part[0] == "tags":
        assert not part[1] and not part[2], 'invalid /tags request'
        for tag in await get_trending_tags(context):
            state['tag_idx']['trending'].append(tag['name'])
            state['tags'][tag['name']] = tag

    elif part[0] in CONDENSER_NOOP_URLS:
        assert not part[1] and not part[2]

    else:
        raise ApiError('unhandled path: /%s' % path)

    return state
예제 #4
0
async def call(context, api, method, params):
    """Routes legacy-style `call` method requests.

    Example:
    ```
    {"id":0,"jsonrpc":"2.0","method":"call",
     "params":["database_api","get_state",["trending"]]}
    ```"""
    # pylint: disable=too-many-return-statements, too-many-branches
    assert api == 'condenser_api', "`call` requires condenser_api"

    # Follows
    if method == 'get_followers':
        return await get_followers(context, *_strict_list(params, 4))
    elif method == 'get_following':
        return await get_following(context, *_strict_list(params, 4))
    elif method == 'get_follow_count':
        return await get_follow_count(context, *_strict_list(params, 1))

    # Content primitives
    elif method == 'get_content':
        return await get_content(context, *_strict_list(params, 2))
    elif method == 'get_content_replies':
        return await get_content_replies(context, *_strict_list(params, 2))

    # Trending tags
    elif method == 'get_trending_tags':
        return await get_trending_tags(context, *_strict_list(params, 2))

    # Content monolith
    elif method == 'get_state':
        return await get_state(context, *_strict_list(params, 1))

    # Global discussion queries
    elif method == 'get_discussions_by_trending':
        return await get_discussions_by_trending(context,
                                                 **_strict_query(params))
    elif method == 'get_discussions_by_hot':
        return await get_discussions_by_hot(context, **_strict_query(params))
    elif method == 'get_discussions_by_promoted':
        return await get_discussions_by_promoted(context,
                                                 **_strict_query(params))
    elif method == 'get_discussions_by_created':
        return await get_discussions_by_created(context,
                                                **_strict_query(params))
    elif method == 'get_post_discussions_by_payout':
        return await get_post_discussions_by_payout(context,
                                                    **_strict_query(params))
    elif method == 'get_comment_discussions_by_payout':
        return await get_comment_discussions_by_payout(context,
                                                       **_strict_query(params))

    # Account discussion queries
    elif method == 'get_discussions_by_blog':
        return await get_discussions_by_blog(context, **_strict_query(params))
    elif method == 'get_discussions_by_feed':
        return await get_discussions_by_feed(context, **_strict_query(params))
    elif method == 'get_discussions_by_comments':
        return await get_discussions_by_comments(context,
                                                 **_strict_query(params))
    elif method == 'get_replies_by_last_update':
        return await get_replies_by_last_update(context,
                                                *_strict_list(params, 3))

    # Exotic account discussion queries
    elif method == 'get_discussions_by_author_before_date':
        return await get_discussions_by_author_before_date(
            context, *_strict_list(params, 4))
    elif method == 'get_blog':
        return await get_blog(context, *_strict_list(params, 3, 2))
    elif method == 'get_blog_entries':
        return await get_blog_entries(context, *_strict_list(params, 3, 2))

    # Misc/dummy
    elif method == 'get_account_votes':
        return await get_account_votes(context, *_strict_list(params, 1))

    raise ApiError("unknown method: %s.%s" % (api, method))
예제 #5
0
async def get_state(path: str):
    """`get_state` reimplementation.

    See: https://github.com/steemit/steem/blob/06e67bd4aea73391123eca99e1a22a8612b0c47e/libraries/app/database_api.cpp#L1937
    """
    (path, part) = _normalize_path(path)

    state = {
        'feed_price': _get_feed_price(),
        'props': _get_props_lite(),
        'tags': {},
        'accounts': {},
        'content': {},
        'tag_idx': {'trending': []},
        'discussion_idx': {"": {}}}

    # account - `/@account/tab` (feed, blog, comments, replies)
    if part[0] and part[0][0] == '@':
        assert not part[1] == 'transfers', 'transfers API not served here'
        assert not part[1] == 'blog', 'canonical blog route is `/@account`'
        assert not part[2], 'unexpected account path[2] %s' % path

        account = valid_account(part[0][1:])
        state['accounts'][account] = _load_account(account)

        if not account:
            state['error'] = 'account not found'
        elif part[1] in ACCOUNT_TAB_KEYS:
            key = ACCOUNT_TAB_KEYS[part[1]]
            posts = await _get_account_discussion_by_key(account, key)
            state['content'] = _keyed_posts(posts)
            state['accounts'][account][key] = list(state['content'].keys())
        elif part[1] in ACCOUNT_TAB_IGNORE:
            pass # condenser no-op URLs
        else:
            # invalid/undefined case; probably requesting `@user/permlink`.
            state['error'] = 'invalid account path requested.'

    # discussion - `/category/@account/permlink`
    elif part[1] and part[1][0] == '@':
        author = valid_account(part[1][1:])
        permlink = valid_permlink(part[2])
        state['content'] = _load_discussion(author, permlink)
        state['accounts'] = _load_content_accounts(state['content'])

    # ranked posts - `/sort/category`
    elif part[0] in ['trending', 'promoted', 'hot', 'created']:
        assert not part[2], "unexpected discussion path part[2] %s" % path
        sort = valid_sort(part[0])
        tag = valid_tag(part[1].lower(), allow_empty=True)
        posts = load_posts(cursor.pids_by_query(sort, '', '', 20, tag))
        state['content'] = _keyed_posts(posts)
        state['discussion_idx'] = {tag: {sort: list(state['content'].keys())}}
        state['tag_idx'] = {'trending': await get_top_trending_tags_summary()}

    # tag "explorer" - `/tags`
    elif part[0] == "tags":
        assert not part[1] and not part[2], 'invalid /tags request'
        for tag in await get_trending_tags():
            state['tag_idx']['trending'].append(tag['name'])
            state['tags'][tag['name']] = tag

    elif part[0] == 'witnesses' or part[0] == '~witnesses':
        assert not part[1] and not part[2]
        raise ApiError("not implemented: /%s" % path)

    elif part[0] in CONDENSER_NOOP_URLS:
        assert not part[1] and not part[2]

    else:
        log.warning('unhandled path /%s', path)

    return state