Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
vik
8 лет назад

⛓ Снятие лимитов в популярной golos/steem JS библиотеке на примере фан-карты Mapala

Голос стал песочницей для множества начинающих разработчиков и просто любителей.
Блокчейн с открытым кодом + дружное сообщество - все это делает голос отличной площадкой для приобретения и прокачки разных навыков взаимодействия с трендовыми технологиями.


В этом посте я приведу пример, который поможет снять некоторые "мнимые" ограничения в API golos/steem
Надеюсь это поможет всем, кому нравится созидать что-то на блокчейне голоса.

Речь пойдет о steem-js она же golos-js и других форках.
Как минимум мы сможем выйти за рамки лимита в 100 постов в API для вызова getDiscussions

Мне это понадобилось в процессе разработки телеграм-бота и фан-карты для mapala.
На карту выводятся все существующие посты с MAPALA в которых есть географические координаты:

Посмотреть вживую можно тут https://chain.cf/mapala - это тестовый пример и весь скрипт выполняется в браузере,посты грузятся достаточно долго. Но при использовании рендера не сервере - это дело нескольких секунд. Я не зря назвал это фан-картой - так как акцентирую, что я не состою в команде разработчиков. То что делаю, это не коммерческие продукты, это скорее просто хобби.

В телеграм боте мне так же понадобилась возможность выводить все посты без ограничений в 100, при этом давая возможность прочесть контент и посмотреть фото прямо в боте.


Над этими и еще над с 10-к проектов идет работа, многое не получается успеть просто физически, а большая часть времени уходит на изучение API и ответы пользователям в тг, надеюсь и буду рад, если мои наработки и потраченное время сэкономят ресурсы таким же энтузиастам :)


Приступим!

Нам вместе с библиотеками golos-js/steem-js поставляется неполная инструкция к вызовам вида:

Get Discussions By Created

golos.api.getDiscussionsByCreated(query, function(err, result) {
  console.log(err, result);
});

Здесь и далее будем рассматривать этот API вызов в качестве подопытного.

Вызов getDiscussionsByCreated - возвращает нам список постов сортированных по дате создания, а query это конкретный запрос диктующий, что именно возвращать. Проблема в том, что на официальной странице либы нет описания того, что нужно вставлять в query и начинающий разработчик-любитель полезет в документацию и увидит что в query должен быть тег и лимит {"tag":"mapala","limit":100}

Скрин со страницы документации https://developers.golos.io/doc/client#discussions

Кроме официальной документации это так же указано в API explorer

Более того, если мы хотим вывести список постов в количестве большем чем 100, то мы получим ошибку.
Например если мой query будет {"select_tags":["mapala"],"limit":101}, то я не получу 101 пост, а получу ошибку

Представьте, что нам нужно выводить подгружаемую ленту постов, эдакий infinity scroll на странице.

Для этого делаем запрос с пустым тегом (это выведет все посты,независимо от тегов):

get_discussions_by_created({"select_tags":["mapala"],"limit":100})

В качестве ответа мы получили максимум 100 постов и плюс ко всему, в этих 100 постах у нас 80 от bm, которые мы скроем, в остатке останется каких-то 20 постов с голоса без возможности подгрузить более ранние...

Долгое время я верил этому искусственному лимиту и он меня порядком раздражал.
Но как оказывается, проблема не в лимитах, а в неполной и недостаточной документации для вызовов.

Поражает, что есть полно не задокументированных возможностей!


картинку украл в комментах у Дена Ларимера :)

Вглянем еще раз на скрин ошибки

Сообщение о лимите api нам показывает файл database_api.hpp. Так как мы работаем с открытом кодом (и это замечательно!) мы можем найти содержимое этого файла в исходниках голоса.
hpp - это расширение для языка C++, идем в репозиторий голоса на github и находим там исходники на C++

Вышеупомянутый файл можно найти по пути /golos/libraries/app/database_api.cpp

Ищем запрос _created и находим его на строке 1467
https://github.com/GolosChain/golos/blob/master/libraries/app/database_api.cpp#L1467

Я не стану приводить весь код, он достаточно объемный, нам нужно изучить строки с 1467 по 1520, что бы узнать, что лимит в js плагинах был искусственный.

Какое на самом деле доступно и может быть query для getDiscussionsByCreated

Кроме всюду упомянутых tag и лимит нам так же доступно вот что:


select_authors
Мы можем указать список авторов

select_tags
Мы можем указать сет тегов, а не только один!

filter_tags
Мы можем убрать из выдачи ненужные теги, например bm-open!

truncate_body
Мы можем сократить контент до короткого описания - например для вывода карточек постов с кратким описанием.

parent_author
Автор-родитель - будут выводится все ответы автору!

parent_permlink
Родительская ссылка - все ответы к определенному посту

start_author и start_permlink
А вот эти 2 параметра помогут сделать offset (отступ) для постов! Это именно то, что мне нужно было - возможность сделать отступ и загружать последовательно все посты на голосе забыв про лимит в 100 постов! Как именно это сделать я напишу ниже.


Бесконечный скролл всех постов голоса

Немного усложним задачу и выведем все посты с mapala в которых есть координаты местности (в клиенте мапала при размещении поста можно указать широту и долготу местности)

Создаем promise и загружаем в posts первые 100 постов с тегом mapala

const POSTCOUNT = 0
const item = []
const LATEST_POSTS = new Promise((resolve, reject) => {
golos.api.getDiscussionsByCreated({"select_tags":["mapala"],"limit":100},(err, posts) => {
    if (err) {
            reject(err)
        }
        else {
            resolve(posts)
        }
})
})

Передаем posts в следующую функцию, где задаем пустой массив nextset

const POSTS_FILTER = (posts) => {
let nextset = {
        start_permlink:'',
        start_author:''
    }

Укажем количество постов которые получили в ответе

let len = posts.length

Создадим цикл для каждого полученного поста

for (let post of posts) {

В переменную meta будем сохранять json_metadata для каждого раунда цикла

        let meta = JSON.parse(post.json_metadata)

Теперь создадим условие, с помощью которого будем обрабатывать только те посты, в которых указаны координаты местности

        if(typeof meta.coordinates !=="undefined" && meta.coordinates.length > 10 ){

Внутри условия мы создадим массив в который будем толкать различные данные постов

item.push({
                author:post.author,
                parent:post.parent_permlink,
                title:post.title,
                body:post.body.replace(/<\/?[^>]+(>|$)/g, ""),
                image:(typeof meta.image === 'undefined')?'/logo.png':meta.image[0],
                payout:post.total_pending_payout_value,
                url:'https://golos.io'+post.url,
                meta:meta,
                time:post.created,
                geo:meta.coordinates
            });

И после, когда мы будем на этапе обработки последнего поста в цикле мы заполним массив nextset автором и ссылкой на последний пост

if(i == len - 1){
            nextset.start_permlink = post.permlink;
            nextset.start_author = post.author;
            NEXT_POSTS(nextset)
        }

Это именно та уловка с помощью которой мы получаем возможность получить следующие 100 постов!

Сначала мы получили 100 первых постов, отфильтровали их по вкусу и данным, запомнили автора и ссылку на последний пост и теперь можем вызвать серию из 100 следующих постов задав полученные автора и ссылку как старт.

Вот так:

const NEXT_POSTS = (nextset) => {
golos.api.getDiscussionsByCreated({
"start_permlink":nextset.start_permlink,
"start_author":nextset.start_author,
"select_tags":["mapala"],"limit":100}

Полученные следующие 100 постов обрабатываем так же как и в предыдущем примере, затем снова сохраняем последнего автора и ссылку и с этим данными снова рекурсивно вызываем функцию NEXT_POSTS

nextset.start_permlink = post.permlink;
            nextset.start_author = post.author;
            if(len > 1){
                NEXT_POSTS(nextset)
                }

Условие if(len > 1) помогает нам перестать вызывать функцию если мы уже получили абсолютно все посты.

Код полностью выглядит так






Вместо PS и вместо отчета делегата.

Народ требует отчетов, но мне просто иногда жаль засирать незыблемость блокчейна очередным отчетом, потому буду краток :)

Хочу напомнить, что вчера вместе с @ropox и @everythink мы запустили @dobrobot - бота который делает добро за ваш счет :) Вы пополняете добробота, а он раздает ваши монеты тем, за кого вы голосуете. Легкий способ почувствовать себя одаривающим китом :)
💱Подробнее

Так же напомню, что моя собственная инициатива @robot так же активно работает и делает добро, но уже за мой счет :) Не забывайте рекомендовать авторов, которым @robot будет оказывать финансовую поддержку.
🎁Подробнее

Кроме этого я принял участие в 10-ке разных ICO в т.ч. #mapala - ребята делают большую работу и скоро она будет показана публике, а сейчас есть возможность приобрести их токены по минимально возможной цене. Можно с уверенностью сказать, что у них все только начинается.

Про golos.io я так же не забыл, это можно видеть из финансовой статистики @arcange

Я в 10-ке пользователей больше всех инвестировавших в силу голоса. (Про голос я узнал только в январе, потому в ICO не участвовал)
К слову - из голоса я еще ни разу не выводил какие-либо средства :)

Из печального...

1. Это, как ни странно то, что я в вышеупомянутой 10-ке... Мне казалось что передо мной будет гораздо больше пользователей. Хотелось бы быть со своими копейками в хвосте.

2. Вторая печаль - это внезапный отказ достаточно дорогого сервера на котором была нода и десяток телеграм ботов которыми активно пользуется народ.

После чего я сразу поднял резервную ноду в другом датацентре - работа была восстановлена в кратчайшие сроки.

На связи

Я почти всегда доступен для обратной связи, признаться на это уходит очень много времени, так как стараюсь отвечать всем.

https://t.me/chain_cf - чат посвященный @robot и тг ботам для голоса
https://t.me/vikxx - личные сообщения
https://chat.golos.io/direct/vik - личные сообщения
https://discord.gg/k6TMZx6 - чат буржуйский.

1
1696.911 GOLOS
На Golos с January 2017
Комментарии (15)
Сортировать по:
Сначала старые