@vik
3 года назад

⛓ Снятие лимитов в популярной 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 - чат буржуйский.

vasaОтветил vik
3 года назад

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

Ответить
ac1dОтветил vik
3 года назад

@vik респект и уважуха тебе! Как, за то, что ты делаешь для Голоса, так и за то, что ты делаешь для Mapala. Очень рад, что есть такие люди, как ты!

Ответить
ontofractalОтветил vik
3 года назад

забавно, я для Glasnost нашел такое же решение и тоже после долгого изучения исходников.

С документацией в Steem и по наследству в Голосе все совсем плохо.

Ответить
t3ran13Ответил ontofractal
3 года назад

самое печатлдьно что теперь апихи отличаются, и это вносить свои неудобства(

Ответить
sheriffОтветил ontofractal
3 года назад

@ontofractal, @t3ran13, какие изменения или улучшения документации вы можете предложить и хотите увидеть?

Команда Голоса. Внимательно.

Ответить
t3ran13Ответил sheriff
3 года назад

документация та, что есть, меня уже устраивает, но она не юзер френдли (нужно убивать море времени чб разобраться)

потом в нашей документации есть ошибки: https://developers.golos.io/doc/client#discussions это сейчас будет работать только для стима, у нас обновилось и тело изменилось, пофиксить нужно. было бы не плохо чб кто-то сдедил и оперативно обновлял инфу, и была какая-то лента новостей с изменениями. я понимаю что в голосе постят, но во первых не все поститься с аккка голоса, очень много важного с личных, это плохо, так и еще это нужно все постоянно читать, не всегда есть время( потому лента с новостями для девелоперов решила бы вопрос. быть может отдельный акк golos-developer для тематических нововстей)

Ответить
sheriffОтветил t3ran13
3 года назад

Спасибо.

Ответить
sheriffОтветил t3ran13
3 года назад

А по юзер-френдли какие предложения? Можно со структурой, примерами и картинками.

Ответить
t3ran13Ответил sheriff
3 года назад

А по юзер-френдли какие предложения? Можно со структурой, примерами и картинками.

самое главное чб приходилось как можно меньше гуглить

  • для начало нужно пофиксить отличный инструмент https://golostools.ru/explorer
  • дать больеш примеров. у нас уже много добровольцев написало море советов и прочего, было бы неплохо все собрать и структурировать
  • ну и опять же, польше комментариев в коде. мне вот в свое время было совсем не очевидно что json-rpc должен быть реализован именно на вебсокетах, а это важно знать)
  • ну и самое важное, как можно больше клиентов на разных языках)

но это ИМХНО, было бы немплохо всех местных "умельцев" поспрошать, чб впечатлениями поделились)

Ответить
sheriffОтветил t3ran13
3 года назад

Спасибо. Мы постараемся как-то учесть все пожелания.

Ответить
t3ran13Ответил vik
3 года назад

поправь, если хотите конкретный тег а не все подряд

  • для голоса: {"select_tags":["your_tag"], "limit":100}
  • для стима: {"tag":"your_tag", "limit":100}

если голосу отдать {"tag":"your_tag", "limit":100}, то получим все подряд посты, без фильтрации по тегам)

используй https://developers.golos.io/doc/d4/dbd/classsteemit_1_1app_1_1database__api.html

Ответить
sheriffОтветил vik
3 года назад

Мы рады создавать и поддерживать нужную атмосферу. Не без недостатков, конечно, но рады тёплым словам.

Команда Голоса.

Ответить
golosboardОтветил vik
3 года назад

@vik Поздравляю! Вы добились некоторого прогресса на Голосе и были награждены следующими новыми бейджами:

Ваш пост получил высшую оплату за один день

Вы можете нажать на любой бейдж, чтобы увидеть свою страницу на Доске Почета. Чтобы увидеть больше информации о Доске Почета, нажмите здесь

Если вы больше не хотите получать уведомления, ответьте на этот комментарий словом стоп

Если вы хотите поддержать проект Доска Почета, вы можете проголосовать за это уведомление.

Ответить
arcangeОтветил vik
3 года назад

@vik, Поздравляю! Ваш пост был упомянут в моем хит-параде в следующих категориях:

  • Голосов - 1 позицию - 151 Голосов
  • Выплаты - 1 позицию - 955,0520 GBG
Ответить
kuklamashaОтветил vik
3 года назад

чет я совсем пропала = ( нет времени и желания писать ты как? как дела?

Ответить
sxiiiОтветил vik
3 года назад

@vik можно ссылку на полный код добавить?... И я так и не понял, как правильно вызов сделать, указав автора... Не работают никакие варианты (через curl).

Ответить