Exemplo n.º 1
0
async def get_content(author: str, permlink: str):
    """Get a single post object."""
    valid_account(author)
    valid_permlink(permlink)
    post_id = get_post_id(author, permlink)
    if not post_id:
        return {'id': 0, 'author': '', 'permlink': ''}
    return load_posts([post_id])[0]
Exemplo n.º 2
0
async def get_content_replies(parent: str, parent_permlink: str):
    """Get a list of post objects based on parent."""
    valid_account(parent)
    valid_permlink(parent_permlink)
    parent_id = get_post_id(parent, parent_permlink)
    if parent_id:
        child_ids = get_child_ids(parent_id)
        if child_ids:
            return load_posts(child_ids)
    return []
Exemplo n.º 3
0
async def get_content_replies(context, author: str, permlink: str):
    """Get a list of post objects based on parent."""
    db = context['db']
    valid_account(author)
    valid_permlink(permlink)
    parent_id = await get_post_id(db, author, permlink)
    if parent_id:
        child_ids = await get_child_ids(db, parent_id)
        if child_ids:
            return await load_posts(db, child_ids)
    return []
Exemplo n.º 4
0
async def get_content(context, author: str, permlink: str):
    """Get a single post object."""
    db = context['db']
    valid_account(author)
    valid_permlink(permlink)
    post_id = await get_post_id(db, author, permlink)
    if not post_id:
        return {'id': 0, 'author': '', 'permlink': ''}
    posts = await load_posts(db, [post_id])
    assert posts, 'post was not found in cache'
    return posts[0]
Exemplo n.º 5
0
async def get_replies_by_last_update(start_author: str, start_permlink: str = '',
                                     limit: int = 20, truncate_body: int = 0):
    """Get all replies made to any of author's posts."""
    ids = cursor.pids_by_replies_to_account(
        valid_account(start_author),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 50))
    return load_posts(ids, truncate_body=truncate_body)
Exemplo n.º 6
0
async def get_discussions_by_comments(start_author: str, start_permlink: str = '',
                                      limit: int = 20, truncate_body: int = 0):
    """Get comments by made by author."""
    ids = cursor.pids_by_account_comments(
        valid_account(start_author),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 20))
    return load_posts(ids, truncate_body=truncate_body)
Exemplo n.º 7
0
async def get_replies_by_last_update(context, start_author=None, start_permlink='',
                                     limit=20):
    """Get all replies made to any of author's posts."""
    assert start_author, '`start_author` cannot be blank'
    ids = await cursor.pids_by_replies_to_account(
        context['db'],
        valid_account(start_author),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100))
    return await load_posts(context['db'], ids)
Exemplo n.º 8
0
async def get_discussions_by_comments(context, start_author=None, start_permlink='',
                                      limit=20):
    """Get comments by made by author."""
    assert start_author, '`start_author` cannot be blank'
    ids = await cursor.pids_by_account_comments(
        context['db'],
        valid_account(start_author),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100))
    return await load_posts(context['db'], ids)
Exemplo n.º 9
0
async def get_discussions_by_blog(tag: str, start_author: str = '',
                                  start_permlink: str = '', limit: int = 20,
                                  truncate_body: int = 0):
    """Retrieve account's blog posts."""
    ids = cursor.pids_by_blog(
        valid_account(tag),
        valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 20))
    return load_posts(ids, truncate_body=truncate_body)
Exemplo n.º 10
0
async def get_discussions_by_created(context, start_author='', start_permlink='',
                                     limit=20, tag=None):
    """Query posts, sorted by creation date."""
    ids = await cursor.pids_by_query(
        context['db'],
        'created',
        valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100),
        valid_tag(tag, allow_empty=True))
    return await load_posts(context['db'], ids)
Exemplo n.º 11
0
async def get_discussions_by_feed(tag: str,
                                  start_author: str = '',
                                  start_permlink: str = '',
                                  limit: int = 20,
                                  truncate_body: int = 0):
    """Retrieve account's personalized feed."""
    res = cursor.pids_by_feed_with_reblog(
        valid_account(tag), valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100))
    return load_posts_reblogs(res, truncate_body=truncate_body)
Exemplo n.º 12
0
async def get_discussions_by_created(start_author: str = '',
                                     start_permlink: str = '',
                                     limit: int = 20,
                                     tag: str = None,
                                     truncate_body: int = 0):
    """Query posts, sorted by creation date."""
    ids = cursor.pids_by_query(
        'created', valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100), valid_tag(tag, allow_empty=True))
    return load_posts(ids, truncate_body=truncate_body)
Exemplo n.º 13
0
async def get_discussions_by_blog(context, tag=None, start_author='',
                                  start_permlink='', limit=20):
    """Retrieve account's blog posts, including reblogs."""
    assert tag, '`tag` cannot be blank'
    ids = await cursor.pids_by_blog(
        context['db'],
        valid_account(tag),
        valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100))
    return await load_posts(context['db'], ids)
Exemplo n.º 14
0
async def get_discussions_by_feed(context, tag=None, start_author='',
                                  start_permlink='', limit=20):
    """Retrieve account's personalized feed."""
    assert tag, '`tag` cannot be blank'
    res = await cursor.pids_by_feed_with_reblog(
        context['db'],
        valid_account(tag),
        valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100))
    return await load_posts_reblogs(context['db'], res)
Exemplo n.º 15
0
async def get_post_discussions_by_payout(context,
                                         start_author: str = '',
                                         start_permlink: str = '',
                                         limit: int = 20,
                                         tag: str = None,
                                         truncate_body: int = 0):
    """Query top-level posts, sorted by payout."""
    ids = await cursor.pids_by_query(
        context['db'], 'payout', valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100), valid_tag(tag, allow_empty=True))
    return await load_posts(context['db'], ids, truncate_body=truncate_body)
Exemplo n.º 16
0
def split_url(url, allow_empty=False):
    """Validate and split a post url into author/permlink."""
    if not url:
        assert allow_empty, 'url must be specified'
        return None
    assert isinstance(url, str), 'url must be a string'

    parts = url.split('/')
    assert len(parts) == 2, 'invalid url parts'

    author = valid_account(parts[0])
    permlink = valid_permlink(parts[1])
    return (author, permlink)
Exemplo n.º 17
0
async def get_discussions_by_hot(context,
                                 start_author: str = '',
                                 start_permlink: str = '',
                                 limit: int = 20,
                                 tag: str = None,
                                 truncate_body: int = 0,
                                 filter_tags: list = None):
    """Query posts, sorted by hot score."""
    assert not filter_tags, 'filter_tags not supported'
    ids = await cursor.pids_by_query(
        context['db'], 'hot', valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100), valid_tag(tag, allow_empty=True))
    return await load_posts(context['db'], ids, truncate_body=truncate_body)
Exemplo n.º 18
0
async def get_discussions_by_comments(context,
                                      start_author: str = None,
                                      start_permlink: str = '',
                                      limit: int = 20,
                                      truncate_body: int = 0,
                                      filter_tags: list = None):
    """Get comments by made by author."""
    assert start_author, '`start_author` cannot be blank'
    assert not filter_tags, 'filter_tags not supported'
    ids = await cursor.pids_by_account_comments(
        context['db'], valid_account(start_author),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100))
    return await load_posts(context['db'], ids, truncate_body=truncate_body)
Exemplo n.º 19
0
async def get_discussions_by_author_before_date(author: str,
                                                start_permlink: str = '',
                                                before_date: str = '',
                                                limit: int = 10):
    """Retrieve account's blog posts, without reblogs.

    NOTE: before_date is completely ignored, and it appears to be broken and/or
    completely ignored in steemd as well. This call is similar to
    get_discussions_by_blog but does NOT serve reblogs.
    """
    # pylint: disable=invalid-name,unused-argument
    ids = cursor.pids_by_blog_without_reblog(
        valid_account(author), valid_permlink(start_permlink,
                                              allow_empty=True),
        valid_limit(limit, 100))
    return load_posts(ids)
Exemplo n.º 20
0
async def get_discussions_by_blog(context,
                                  tag: str = None,
                                  start_author: str = '',
                                  start_permlink: str = '',
                                  limit: int = 20,
                                  truncate_body: int = 0,
                                  filter_tags: list = None):
    """Retrieve account's blog posts, including reblogs."""
    assert tag, '`tag` cannot be blank'
    assert not filter_tags, 'filter_tags not supported'
    ids = await cursor.pids_by_blog(
        context['db'], valid_account(tag),
        valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 100))
    return await load_posts(context['db'], ids, truncate_body=truncate_body)
Exemplo n.º 21
0
async def get_discussions_by_feed(tag: str, start_author: str = '',
                                  start_permlink: str = '', limit: int = 20,
                                  truncate_body: int = 0):
    """Retrieve account's personalized feed."""
    res = cursor.pids_by_feed_with_reblog(
        valid_account(tag),
        valid_account(start_author, allow_empty=True),
        valid_permlink(start_permlink, allow_empty=True),
        valid_limit(limit, 20))

    reblogged_by = dict(res)
    posts = load_posts([r[0] for r in res], truncate_body=truncate_body)

    # Merge reblogged_by data into result set
    for post in posts:
        rby = set(reblogged_by[post['post_id']].split(','))
        rby.discard(post['author'])
        if rby:
            post['reblogged_by'] = list(rby)

    return posts
Exemplo n.º 22
0
async def get_reblogged_by(context, author: str, permlink: str):
    """Get all rebloggers of a post."""
    return await cursor.get_reblogged_by(context['db'], valid_account(author),
                                         valid_permlink(permlink))
Exemplo n.º 23
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
Exemplo n.º 24
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 part[1] not in ACCOUNT_TAB_IGNORE:
            assert part[1] in ACCOUNT_TAB_KEYS, "invalid acct path %s" % path
            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())

    # discussion - `/category/@account/permlink`
    elif part[1] and part[1][0] == '@':
        author = valid_account(part[1][1:])
        permlink = valid_permlink(part[2])
        post_id = get_post_id(author, permlink)
        state['content'] = _load_posts_recursive([post_id]) if post_id else {}
        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 Exception("not implemented: /%s" % path)

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

    else:
        print('unhandled path /%s' % path)

    return state