Многие уже в курсе способностей сервисного робота @gemini работающего в ГОЛОСе.
Публикую код робота, только ту его часть, которая отвечает непосредственно за апвоуты по вызову пользователей (погодная часть из публикуемого кода изъята).
Робот работает на ноде. Часть его собрана по исходному коду @vik.
Я не программист, особенно в части ява. С ней я связался исключительно из-за любопытства и доступностью примеров опубликованных ранее @vik. Можно сказать, что этот робот был написан в третий присест за изучением Node.js
Внутри кода я написал комментарии. Если их недостаточно, то отвечу на вопросы.
Сменив ник робота в коде, постинг ключ, а так же ключевую фразу для активации робота - у Джемини появится брат-близнец.
const Promise = require("bluebird")
const _ = require('lodash')
const golos = require('steem')
golos.config.set('websocket','wss://ws.golos.io');
golos.config.set('address_prefix','GLS');
golos.config.set('chain_id','782a3039b478c839e4cb0c941ff4eaeb7df40bdd68bd441afd444b9da763de12');
//----------------------------
var k='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; //постинг ключ робота
var account='gemini'; //аккаунт робота
var percent=2500;//сила голоса апвоута (25%)
// фикс обработки несуществующих блоков
let trig = {
existBlock:true
}
// получение глобальных динамических данных
const dynamicSnap = new Promise((resolve, reject) => {
golos.api.getDynamicGlobalProperties((err, res) => {
if (err) {
console.log(err)
}
else {
resolve(res)
}
})
})
// получение номера последнего блока
const FIRSTBLOCK = n => n.head_block_number
// достаем операции из транзакций
const OPS = (ops) => {
return _.flatten(ops.transactions.map(tx => tx.operations))
}
// фильтруем операции
const OPSFILTER = (operation) => {
const [type, data] = operation
// определяем операцию размещения комментария
if (type === 'comment' && data.title==='') {
//определяем, что позвали нашего робота
if (data.body.substring(0,11)==="@gemini up!") {
$author=data.author; //определяем автора комментария
$permlink=data.permlink; //определяем пермлинк комментария
oncomm=level (); //определяем уровень комментария
//+------------------------------------------------------------------+
//| функция определения уровня комментария |
//+------------------------------------------------------------------+
function level (){
var lvl = $permlink; // пермлинк комментария
var target = "-re-"; // цель поиска в пермлинке
var pos = 2; //начинаем с третьей позиции (так как первые символы 're-' отличаются от цели)
var count=0; //начальный счётчик ставим в нуль
while (true) { //запускаем цикл поиска
var foundPos = lvl.indexOf(target, pos);//индекс найденой позиции цели
if (foundPos == -1) break; //если дошли до конца пермлинка, прекращаем цикл поиска
pos = foundPos + 1; //нашли цель, начинаем поиск со следующей позиции
count = pos-foundPos+count; //считаем количество найденых целей
if (count===4) return count; //если целей 4 штуки (5-й уровень комментария) значения счётчика определено, до этой цифры значение 'undefined'
}
}
//+------------------------------------------------------------------+
//пока значения уровня комментария не определено (робот может разместить ответный комментарий)
if (oncomm===undefined){
parentAuthorAns=data.parent_author; //определяем автора родительского комментария (или поста)
parentPermlinkAns=data.parent_permlink;//определяем пермлинк родительского комментария (или поста)
permlinkcomm='re-'+$author+'-'+$permlink;//формируем пермлинк ответного комментария робота
t=""; //титры (название) ответного комментария робота (пустое значение для комментариев)
jsonMetadata=data.json_metadata;//дублируем метадату json
//запрашиваем данные по контенту к которому оставлен комментарий
golos.api.getContent(parentAuthorAns,parentPermlinkAns, function(err, result){
tlt=result.title; //определяем титры (назвние) контента
ath=result.author; //определяем автора контента
path=result.parent_author; //определяем автора родителя контента
avotes=result.active_votes;//определяем пользователей проголосовавших за контент
onvot = vt (); //определяем голос робота (голосовал или нет)
//+------------------------------------------------------------------+
//| функция поиска голоса робота за контент |
//+------------------------------------------------------------------+
function vt (){
let str =''; //присваиваем пустое начальное значение возвращаемой переменной
for(let i = 0; i < avotes.length; i++) { //запускаем цикл поиска в массиве пользователей проголосовавших за контент
if( avotes[i].voter == account){ // если находим робота
str='1'; //возвращаемой переменной присваиваем значение '1'
break; //останавливаем цикл
} else str='0';//если робота среди проголосовавших нет, то присваиваем перменной значение '0'
}
return str; //возвращаем значение функции
}
//+------------------------------------------------------------------+
//если титры(название) контента не пустое значение (это пост)
//и автор родительского комментария(поста) является автором контента
//и автор родитель контента пуст
//и нет робота среди проголосовавших за контент
if(tlt!="" && parentAuthorAns==ath && path=="" && onvot=='0'){
golos.broadcast.vote(k, account, parentAuthorAns, parentPermlinkAns, percent, function(err, result) {console.log(err, result); }); //голосуем за пост
post_body="<html><p>Ок, @"+$author+'!</p><p> Я проголосовал за пост: <a href="https://golos.io/@'+ath+"/"+parentPermlinkAns+'">'+tlt+'</a></p></html>'; //формируем тело ответного комментария
golos.broadcast.comment(k,$author,$permlink,account,permlinkcomm,t,post_body,jsonMetadata,function(err, result) {console.log(err, result); }); //размещаем ответный комментарий робота
}
//или если робот голосовал за контент
else if(tlt!="" && parentAuthorAns==ath && path=="" && onvot=='1'){
post_body="<html><p>@"+$author+', я уже голосовал за этот пост.</p></html>'; //формируем тело комментария
golos.broadcast.comment(k,$author,$permlink,account,permlinkcomm,t,post_body,jsonMetadata,function(err, result) {console.log(err, result); }); //размещаем ответный комментарий робота
}
//или если титры (название) контента отсутствуют
//и автор родитель контента не пуст, то это комментарий к комментарию (т.е. комментарий не первого уровня, не к посту)
else if(tlt=="" && path!="" ){
post_body="<html><p>@"+$author+', если необходим мой апвоут за пост, то позовите меня в комментарии первого уровня.</p></html>';//формируем тело ответного комментария
golos.broadcast.comment(k,$author,$permlink,account,permlinkcomm,t,post_body,jsonMetadata,function(err, result) {console.log(err, result); }); //размещаем ответный комментарий робота
}
});
}
}
}
}
// получение данных каждого блока
const SENDBLOCK = currentblock => {
golos.api.getBlock(currentblock, (err, result) => {
if (err) {
console.log(err)
}
else if (result === null){
// если блок не существует активируем триггер
trig.existBlock = false
}
else {
// если блок существует и не было ошибки - отправляем блок в функцию фильтра операций
OPS(result)
.forEach(OPSFILTER)
trig.existBlock = true
}
})
}
// определяем стартовый блок на начало работы скрипта
// каждые 3 секунды увеличивае номер блока на 1
const NEXTBLOCKS = firstblock => {
let currentblock = firstblock
setInterval(() => {
// Увеличиваем только если предыдущий блок был корректно обработан
if(trig.existBlock){
currentblock++
}
SENDBLOCK(currentblock)
}, 3000)
}
// запускаем основные функции через обещания (promises)
dynamicSnap
.then(FIRSTBLOCK)
.then(NEXTBLOCKS)
.catch(e => console.log(e));
Этот же робот легко адаптируется для работы вне Node, непосредственно в браузере в виде вкладки или приложения. А небольшое видоизменение кода позволит его настроить на избранных кураторов (ников) и/или ограничить права на использование по репутации и другим параметрам.
Способы модернизации опубликую чуть позднее.
Спасибо за интересного бота и его код!
Надеюсь, в ближайшее время у Gemini появятся братья!
Отличный пост, спасибо @investigator!! Ждем появления аналогов;)
@gemini up!
@forbon21, я уже голосовал за этот пост.
Ваш пост поддержали следующие Инвесторы Сообщества "Добрый кит":
yefet, vas, mir, natalia, andrvik, lelya, urii, larissa, investigator, forbon21, yurgent71, vasilisapor2, chika25, semasping, svinsent, ruta, boltyn, vika-teplo, baltiyka, del137, nerengot, lokkie, abloud, tatdt, ksantoprotein, xsen, anr
Поэтому я тоже проголосовал за него!
Если Вы проголосуете за этот комментарий, то поможете сделать "Доброго Кита" сильнее!
Как начать пользоваться ботом?
отличный вопрос :)
Джемини работает круглосуточно. Подробнее о нём: https://golos.id/ru--golos/@investigator/golosovye-servisy
Если вы хотите своего робота, то просто копируйте код, меняйте аккаунт робота (ник), постинг ключ и ключевую фразу.
var k='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'; //постинг ключ робота
var account='gemini'; //аккаунт робота
...
"@gemini up!"
Запускайте на Node.
Извините.
Я далёк от программирования. Другая профессия.
Не могли бы ещё подробнее обьяснить. Для чайников. Как его запустить в работу.
Я конечно подписался на Вас и буду дальше читать и изучать. Именно поэтому мне нужна небольшая помощь
Это код работающего робота @gemini
Робот отдан в общественное пользование (может воспользоватся абсолютно любой пользователь ГОЛОСа).
Для того, чтобы робот проапвотил какой-нибудь пост. Надо в комментарии к посту(который хотим вознаградить) набрать команду:
@gemini up!
(Комментарий должен начинаться только этой фразой.) Робот услышит, что его позвали и проголосует за пост. Не имеет значения чей пост, ваш или другого ника.
Как в принципе запускаются роботы на Node.js, это тема отдельного разговора, если есть потребность обязательно напишу.
Понял. Щас попробую ))
Здравствуйте! Обязательно напишите - думаю, многим будет полезно. С меня подписка!
@maximus00, уже написано
https://golos.id/ru--golos/@investigator/vzaimodeistvie-s-node-js-or-1
https://golos.id/ru--golos/@investigator/vzaimodeistvie-s-node-js-or-2
Напишите, пожалуйста, очень интересно. Хотя бы в общих чертах.
Извиняюсь что не по теме. @investigator скажите пожалуйста, какой запрос нужен для выгрузки аккаунтов с наибольшим количеством комментариев за день с базы данных голоса? Хочу попробовать сделать что-то типа "Топ комментаторов за день".
Я, @dimas, выгружал все за сутки, а отсеивал уже в Excel.
Пользуюсь фильтрами в HeidiSQL (подробнее здесь: https://golos.id/ru--golos/@investigator/kak-polzovatsya-bazoi-dannykh-golosa-or-2)
Там и примеры фильтров.