Код робота голосующего за посты по вызову избранных пользователей
В комментариях, в разговоре с @gidlark, понял, что есть потребность в роботе наподобие @gemini, но применительно к группам кураторов (избранных пользователей).
Например, есть группа (сообщество) которая создала свой общий аккаунт для робота. Наделила этот аккаунт силой голоса и использует для апвоутинга любых постов, но только по вызову участников этой группы. В зависимости, от внесённой СГ для робота, каждому участнику назначается определённый процент использования СГ робота.
Ниже шаблон такого кода и некоторые разъяснения
В секции Данные робота пишем аккаунт вашего робота и его постинг ключ. В коде для примера прописан аккаунт @gemini, а постинг ключ заменён на X.
var account='gemini'; //аккаунт робота который будет апвоутить посты по вызову кураторов (пользователей)
var k='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; //постинг ключ робота
Назначить пользователей, которых будет слушать робот, можно разными вариантами. Если пользователей не много, то использовать массивы не целесообразно (Вообще, это на вкус. Всё работает и так и эдак).
В коде я выделил секцию Назначаем пользователей, где надо прописать пользователей. В коде для примера назначены два: @investigator и @vladomsk. Таким же синтаксисом прописываете требующиеся вам:
if(data.author=='investigator'||data.author=='vladomsk'){
Для назначения процента использования силы апа робота по пользователям (которых назначили выше) надо в функции назначения силы апвоута присвоить значения. В коде, так же, пример.
if($author=='investigator')str=5000; //для пользователя назначаем величину СГ робота (50%)
if($author=='vladomsk')str=2500;//для пользователя назначаем величину СГ робота (25%)
Код робота написан, подразумевая, что пользователи (кураторы) знают - вызов робота только из комментария первого уровня к посту.
Группам пользователей (или пользователя владельца робота) надо придумать ключевую фразу, на которую будет реагировать робот.
В коде для примера использована: curator up! Обращаю особое внимание, что эта фраза понятна роботу, только если написана с начала комментария (индекса 0 и заключена в пределах 11 знаков, т.е. до 11 индекса). Следовательно, если вы придумаете фразу длиннее или короче, то значения в поиске подстроки data.body.substring(0,11)
надо менять в соответствие вашей ключевой фразе.
Ключевая фраза в коде прописывается здесь:
if (data.body.substring(0,11)==='curator up!') {
Вообще, в принципе, методов нахождения ключевых фраз (слов) есть множество вариантов, опять же - это дело вкуса и потребностей.
Робот запускается на Node.js и требует три библиотеки:
- bluebird
- lodash
- steem
Копируйте код, видоизменяйте в соответствие с вашими хотелками и пользуйтесь:
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 account='gemini'; //аккаунт робота который будет апвоутить посты по вызову кураторов (пользователей)
var k='XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'; //постинг ключ робота
//-------------------------------------------------
// фикс обработки несуществующих блоков
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.author=='investigator'||data.author=='vladomsk'){ // если комментарий размещен избранными пользователями, то идём дальше
//--------------------------------------------------------------------
// если в комментарии прозвучала ключевая фраза (с начала комментария, индекса 0 до 11) идём дальше
if (data.body.substring(0,11)==='curator up!') {
$author=data.author; //определяем автора комментария
$permlink=data.permlink; //определяем пермлинк комментария
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 (); //определяем голос робота (голосовал или нет)
percent=vp($author);//сила голоса апвоута робота для курирования (назначается по избранным пользователям)
// функция поиска голоса робота за контент
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; //возвращаем значение функции
};
// функция назначения силы апвоута по избранным пользователям
function vp($author){
let str = '';//присваиваем пустое начальное значение возвращаемой переменной
if($author=='investigator')str=5000; //для пользователя назначаем величину СГ робота (50%)
if($author=='vladomsk')str=2500;//для пользователя назначаем величину СГ робота (25%)
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); }); //размещаем ответный комментарий робота
}
//---------------------------------------------------------------
});
}
}
}
}
// получение данных каждого блока
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));