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

Блокнот + JavaScript + голос = Трансляция Апвотинга, Фолловинга, новых пользователей, голосов за делегатов и прайсфида.

Продолжение урока

Предыдущий урок здесь: Доступный JavaScript на прикладном примере создания страницы/сайта с действиями пользователей голоса в реальном времени

В прошлых уроках мы начали разбирать состав javascript с созданной в блокноте странички, которая транслирует статистику голоса в реальном времени, мы научились посылать запросы голосу и получать на них ответы.
Тестовый пример https://vikx.tumblr.com/
qw.gif

В этом посте мы научимся фильтровать и выводить получаемые данные от голоса:

  • Голоса за пользователей и сила отданного голоса
  • Комментарии к постам
  • Создание постов
  • Фолловинг
  • Прайс фиды от делегатов со стоимостью пары (Золотой/Голос)
  • Голосования за делегатов
  • Новые пользователи на голосе

Такая фильтрация удобна тем, что каждый ответ от голоса мы сможем на своей странице оформить по - своему.
Например на тестовой странице https://vikx.tumblr.com/ у нас лента вида:

  • Вася комментирует петю - Привет вася!
  • Оля голосует за Колю с силой 10000
  • Лариса подписывается на Альберта
    Но по сути мы получаем только массив разделенных данных, что дает нам возможность оформить выдачу данных как угодно. Мы просто сможем подставлять имена в наши заготовки применяя разные практики визуализации.

Ответы запутанные для человеческого глаза, но удобные для обработки нашим приложением.
Мы научимся их обрабатывать и вставлять в нашу страницу приложения.

Прежде мы научились запрашивать данные из блоков get_block. Такой запрос возвращает нам общий массив данных из блока, которые мы отфильтруем до транзакции > операции:
blockdata = JSON.stringify(data.result.transactions[0].operations[0]);
И в переменной blockdata у нас будет один из множества вариантов содержания операции. Сперва рассмотрим голосования (апвотинг)

Кто за кого голосует в реальном времени

Если в блоке было зафиксировано голосование, то отобразится оно следующим образом:

["vote", {
    "voter": "dmilash",
    "author": "elixir-golos",
    "permlink": "reliz-exgolos-v0-2-open-sors-jsonrpc-klient-dlya-golosa-na-elixir-erlang",
    "weight": 5000
}]
  • voter - тот кто проголосовал
  • author - тот за кого голосовали
  • permlink - ссылка на пост
  • weight - вес голоса

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

Например что бы получить значение voter, нам нужно в переменную записать путь до значения voter.
data.result.transactions[0].operations[0][1].voter;
для автора
data.result.transactions[0].operations[0][1].author;
И так далее. Облегчим и сократим код: поскольку у нас строки отличаются только окончанием, мы сделаем сокращение для одинаковых частей строки. Сокращенная версия будет в переменной tx.
tx = data.result.transactions[0].operations[0][1];
И теперь мы можем выбирать объекты сокращенными строками

tx = data.result.transactions[0].operations[0][1];
$voter = tx.voter; // 
$power = tx.weight;
$author = tx.author;
$permlink = tx.permlink;

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

Но есть проблема в фильтрации данных, что бы стало понятней, перейдем к следующему виду операции - комментариям

Разделяем голоса от комментариев и других данных

Комментарии в нашем потоке выглядят так. К слову с префиксом comment в блоках еще и создаваемые посты, что не очень удобно.

["comment", {
    "parent_author": "whiskardi",
    "parent_permlink": "re-anela-re-toplight-re-konstantin-
nuzhno-li-v-golose-razzhiganie-nenavisti-
oskorbleniya-i-neuvazhenie-pravil-soobshestva-20170203t150954836z",
    "author": "smolalit",
    "permlink": "re-whiskardi-re-anela-re-toplight-re-konstantin-nuzhno-li-v-golose-razzhiganie-nenavisti-oskorbleniya-i-neuvazhenie-pravil-soobshestva-20170203t165212985z",
    "title": "",
    "body": "Ну не всех :))) Но и им (быдлам) там местечко найдется.",
    "json_metadata": "{\"tags\":[\"ru--golos\"]}"
}]

Теперь о проблеме.
Заметили, что в комментариях тоже есть переменная author как и в голосовании? То есть во время приемов блоков, нашему скрипту надо как-то явно указывать, где author в рамках комментария, а где в рамках голосования и т.д. Если мы хотим выводить оформленные данные для каждой операции, нам нужно как-то разделить эти операции по типу данных.

Мы видим, что апвот от коммента отличается первым значением:

["vote", {
  // данные
}]

["comment", {
   // данные
}]

vote и comment. Сделаем переменную, которая будет сохранять категорию данных
trigger = data.result.transactions[0].operations[0][0];
Переменная триггер теперь содержит значение вида vote, comment или другое, которое мы будем получать.
Приступим к выводу стрима на нашу страничку!

Для этого мы заранее должны были создать элемент на странице, куда будем вставлять данные.
Мы создали такой:

<div id="filterdata"> </div>

По вкусу оформили его в css, например я сделал одну колонку с фильтрованными данными, а вторую с нефильтрованными, что бы ничего не пропускать и видеть несоответствия в логике выдачи данных. А логику я придумал такую:

Внутри условия, которое вы должны помнить по прошлому посту

if (data.id === 3 && merkle !== "0000000000000000000000000000000000000000"){

"Если это ответ на запрос с id 3 (который запрашивает данные блока) и блок не пустой, то делать:"
Перечисляем наши переменные со значениями

tx = data.result.transactions[0].operations[0][1];
    trigger = data.result.transactions[0].operations[0][0];
        $voter = tx.voter;
        $power = tx.weight;
        $author = tx.author;
        $permlink = tx.permlink;
// Это далеко не все, которые нужно создать!
// Просто пока работаем с выводом только голосований

И теперь делаем условие по типу данных:

if (trigger == 'vote'){
        // Что-то сделаем тут
        }

Условие звучит как "Если триггер vote (голосование), то выполнять действие.
Нашим действием будет - вставка значений голосования в страницу, в div элемент #filterdata.
Для этого воспользуемся JS функцией вставки html в начало элементов:
document.getElementById('filterdata').insertAdjacentHTML('afterbegin',votehtml);
Итого, в случае, если в полученном блоке у нас есть операция голосования, срабатывает триггер vote и мы вставляем в страницу данные, наши данные это 4 переменные , которые мы должны вместе с html поместить в переменную votehtml и вставить в div#filterdata
Состав переменных для голосования:

  • $voter =Голосующий;
  • $power = Сила;
  • $author = Автор;
  • $permlink = Ссылка;
    Расположим их для вставки, смешав с html текстом, что бы это имело какой-то вид
votehtml = '<div>'+$voter+' голосует за '+$author+'. Сила '+$power+' </div>'

Теперь в наш поток данных понятен глазу. Снизу неоформленное голосование, сверху оформленное.
voteforvote.jpg
Я не стал добавлять ссылку на пост, хотя в переменную votehtml вы можете вставить переменные с именами, ссылками и силой как угодно, можно стилизовать имена цветами, добавить иконку апвотинга, что бы было понятно, что это голосование, так же можно и присвоить аватарки пользователям (это будет в следующих постах).

Собственно основной путь пройден, самое важно на голосе - голоса, и теперь мы можем вывести поток голосов где захотим. Можно на своем сайте, можно смотреть страницу с пк, можно вставлять ее в виде iframe себе или другим продвигая голос :)

Комментарии.

Сложнее из-за смеси данных.

Приступим к разбору комментариев. Так же как и для голосований, мы сделаем условие-фильтр с триггером comment:

if (trigger == 'comment'){
        // создадим и вставим элемент с комментарием    
        }

Проблема будет в том, что в базе голоса объект comment смешан с постами. То есть и новые посты, и новые комменты к постам, будут в данном массиве.

Вот к примеру массив данных комментария:

["comment", {
    "parent_author": "grumlin",
    "parent_permlink": "vazhnoe-pravilo-estafety-10-faktov-o-sebe",
    "author": "galager",
    "permlink": "re-grumlin-vazhnoe-pravilo-estafety-10-faktov-o-sebe-20170203t192929846z",
    "title": "",
    "body": "а если я отредактировала и 
  поставила этот тег первым,
  а в итоге он все равно второй, что делать?
  доктор, это лечится? я умру?",
    "json_metadata": "{\"tags\":[\"ru--novostx\"]}"
}]

А вот массив данных обычного поста

["comment", {
        "parent_author": "",
        "parent_permlink": "ru--kodirovka",
        "author": "redhat",
        "permlink": "kak-kodiruyut-ot-alkogolizma",
        "title": "Как кодируют от алкоголизма?",
        "body": "Текст поста.......................... ","
        json_metadata ":" {\
            "tags\":[\"ru--kodirovka\"]}"
        }]

Если мы сделаем вывод комментариев как-то так

 author+  комментирует parent_author+: 
title + body

То в итоге у нас в первом случае (в случае комментария) будет так:

grumlin комментирует galager:
" "
"а если я отредактировала и
поставила этот тег первым..."

" " пустые кавычки, так как в комментарии title не заполнен.

Во втором случае (в случае с постом) у нас будет:

redhat комментирует " "
Как кодируют от алкоголизма?
Текст поста..........

Опять пустые кавычки, так как в случае с созданием поста не указан parent_author.
Таким образом, нам нужно поделить комментарии на два вида: собственно комментарии и новые посты. Отличить их можно отсутствием parent_author. Технически не отсутствием, а пустым значением " ".
Для этого сделаем еще одно условие внутри условия "если (триггер = коммент)".
Но сначала сделаем переменные с недостающими данными.

$parent = tx.parent_author; // Родитель-автор. Тот кого комментят. Есть только в комментах
$body = tx.body; // Тело коммента или поста
$title = tx.title; // Заголовок. Есть только в постах

Добавим их к списку наших переменных, помним - переменная для author у нас уже есть.

Условие разделения постов от комментариев с последующим размещением на странице.

/// Если триггер равен комменту
if (trigger == 'comment'){
// Если в блоке с данными автор родитель не является пустым значением
            if ($parent !== ""){
 // Выводим сообщение заточенное под комментарий
commthtml = '<div id="item" class="myJson">'+$author+' комментирует '+$parent+': '+$body+' </div>'
document.getElementById('filterdata').insertAdjacentHTML('afterbegin',commthtml);
//В ином случае, если автор родитель пустое значение, то это пост и выводим другой html
         } else { 
// html заточенный под пост.
posthtml = '<div id="item" class="myJson">'+$author+' разместил пост <h4>'+$title+'</h4>'+$body+'</div>'
document.getElementById('filterdata').insertAdjacentHTML('afterbegin',posthtml);
            }
        }

У нас получилось!
Теперь в нашей ленте видно голосования, комментарии (вместе с их содержимым) и новые посты.
[mobvi.gif
На данном этапе наш JavaScript таков:

Подключение и отправка запроса на динамические данные с интервалом 3000ms
[js1

Хуки для точного роста блоков 1 в 3 сек. И отправка запросов на данные аккаунта и содержание блоков
[js2

Обработка полученных данных от блока и вывод голосований, комментариев и постов в ленту на странице
[JS3
Фрагмент кода на последнем скрине будет нашим основным полем деятельности и мы продолжим делать вывод остальных данных

Что еще хотим вывести
  • Подписки
  • Упоминания и транзакции
  • Регистрация новых пользователей
  • Обновление аккаунтов
  • Текущую силу голоса
  • Форму для указания стартового блока
  • Форму для поиска данных по желаемому аккаунту
  • Торги на внутренней бирже (?)
  • Ввод/Вывод токенов пользователями (?)

Выводим подписки (фолловинг)

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

["custom_json", {
    "required_auths": [],
    "required_posting_auths": ["on0tole"],
    "id": "follow",
    "json": "[\"follow\",{\"follower\":\"on0tole\",\"following\":\"piranya\",\"what\":[\"blog\"]}]"
}]

Когда мы будем получать в ответе такую операцию, в триггер будет записываться custom_json - сделаем условие:

// Если триггер custom_json (обычно это фолловинг)
            if (trigger == 'custom_json'){ 
                // тут будем выполнять остальные действия связанные с подпиской
            }

Теперь нам нужно указать в переменных путь до конкретных объектов с данными. Тут немного сложней чем было раньше, так как информация о фолловинге вложена матрешкой в custom_json > json

custom_json", {
....
  "json": "[\"follow\",{\"follower\":\"on0tole\",\"following\":\"piranya\",\"what\":[\"blog\"]}]"
}

Нам нужно добраться до follower и following и записать их в переменные
Вот как мы поступим:

var follow = JSON.parse(tx.json)[1], 
$follower = follow.follower, 
$followin = follow.following; 

В первую переменную мы добавили путь к свойству json при этом применили JSON.parse для перевода строки json в объекты
Во вторую и третью мы добавили имя фолловера и фолло.. фолловнящегося :)

По уже известному принципу мы сможем вывести переменные в желаемом для нас html формате
фолловинг
Фрагмент кода который отвечает за вывод фолловинга:
фолловинг
Не исключено, что custom_json будет в будущем нести и другие данные.

Трансферы, упоминания

Еще один вид операции который мы можем увидеть в потоке - transfer

Это может быть передача личных средств

["transfer",{"from":"polyideic","to":"mapala.ico","amount":"80.000 GBG","memo":"polyideic"}]

Работа mention bot тоже из категории трансферы

["transfer",{"from":"mentionbot","to":"vik",
               "amount":"0.001 GOLOS",
               "memo":"Вас упомянул пользователь...."
}]

Ну и все остальное, что вы можете найти у себя в кошельке на вкладке /transfers

Для нас это уже должно быть легко, создаем переменные и оформляем html
trans.png

На выходе получаем:

mention.png
или так
спасибки

Прайс фиды от делегатов

Возможно нам так же будет интересно вывести котировки от делегатов.

["feed_publish", {
    "publisher": "jesta",
    "exchange_rate": {
        "base": "1.780 GBG",
        "quote": "1.000 GOLOS"
    }
}]

Привычным алгоритмом: если триггер feed_publish, затем переменные, затем вставляем на страницу.
jsfeed.png

Теперь и актуальные прайсфиды валют голоса в нашем потоке!
pfeed.png

Новые пользователи

Данные о создании аккаунта:

["account_create", {
    "fee": "5.000 GOLOS",
    "creator": "golosio",
    "new_account_name": "irinativa",
    "owner": {
        "weight_threshold": 1,
        "account_auths": [],
        "key_auths": [
            ["GLS6R8eeA9rk3ec5WK43bYWrGbWK2XQYWPGjgThwDi4eeZuoPDC3g", 1]
        ]
    },
    "active": {
        "weight_threshold": 1,
        "account_auths": [],
        "key_auths": [
            ["GLS7pX2CGTcS7XjtiLJTTo6GLU4f5FNNh7sM3HpUxkvdtFE9ki87W", 1]
        ]
    },
    "posting": {
        "weight_threshold": 1,
        "account_auths": [],
        "key_auths": [
            ["GLS85fULzSASb3XgW85kwMMmed5vCLS5PXCi3v7Ab8x4Ljo1ZyTNm", 1]
        ]
    },
    "memo_key": "GLS6Cbq4u1gHo8ZGUjj1YXGHrBNnmRtwS5oXvWvGPFP2qvR8FKXLc",
    "json_metadata": "{}"
}]

Нам интересно только new_account_name. Но так как в последнее время много новых аккаунтов с БМ, мы будем брать в переменную еще и creator. Так как у БМ он другой.

Создание акка

Кроме того мы можем видеть и обновление аккаунтов триггером account_update - но я не заметил интересных данным там, так как пока обновлять в аккаунте пользователям особо нечего

Голоса за делегатов

["account_witness_vote", {
    "account": "good-karma",
    "witness": "phenom",
    "approve": true
}]

Пишем привычное условие
Создание акка

И на 4-й строчке:
Делегаты

Заключение

Итак, мы научились выводить самые интересные действия пользователей используя при этом обычную html страничку. Добавив интересную анимацию и оригинальный дизайн страницы - вы сможете повесить ее на любой беплатный хостинг или блоговый движок, который позволяет редактировать шаблоны.
А используя Service Worker или PWA вы сможете из страницы сделать кросс платформенное приложение.
Разумеется, базовый функционал желательно расширить. Фильтры по юзернеймам, датам и событиям, возможность голосования и многое другое, что нам предложит api голоса.

А как насчет iframe баннера на вашем сайте для привлечения пользователей? :)

Реклама голоса, в которой будет фид активности, красноречиво говорящей о том, что голос платформа, где за пользу вам платят:
xx

Продолжение следует!

Ссылки:

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