Бот для пасивного заробітку в Steemit (частина 2)
До написання цього допису мене мотивував власний допис, в якому я навів приклад бота, який працює з сайтом Steemit і голосує за нові дописи. Його можна назвати ботом для пасивного заробітку, але вам і так зрозуміло, що для відчутнішого доходу у вас повинно бути багато SP. Як би там не було, у мене виникла ідея внести деякі зміни в код, щоб бот міг голосувати за дописи, автори яких повинні отримати за них винагороду в найближчі 24 години.
Ще до того як взятися за справу, я підозрював, що ідея провальна, адже за останню добу перед виплатою навряд чи ви отримаєте багато винагороди за кураторство. Якось чисто по-людськи це не здавалося нелогічним. Нікому б не сподобалася схема, що працює за принципом "Прийшов, побачив, переміг" ("Veni, vidi, vici"). Але я вирішив спробувати, щоб переконатися в цьому.
Як і в попередньому прикладі, для запуску JavaScript ми будемо використовувати середовище Node.js. Інструкції з установки та базового налаштування доступною мовою — тут.
Спочатку розберемо основні складові елементи скрипта:
1. Підключення dsteem
const dsteem = require('dsteem');
const client = new dsteem.Client('https://api.steemit.com', {
timeout: 10000,
failoverThreshold: 3
});
Щоб працювати з блокчейном Steem, насамперед потрібно підключити бібліотеку dsteem і вказати деякі параметри: timeout
— максимальний час очікування відповіді та кількість невдалих спроб — failoverThreshold
.
2. Облікові дані
const username = '';
const postingKey = '';
Потрібно вказати ваше ім’я користувача Steemit і постінговий приватний ключ.
3. Налаштування дати
function getCurrentDateTime()
Ця функція призначена для відображення дати та часу в сповіщеннях.
4. Основна функція
function voteTopPosts()
Функція виводить у консоль повідомлення про початок обробки даних. Рядок client.database.call('get_post_discussions_by_payout', [{ tag: '', limit: 100 }]);
готує 100 дописів із найбільшою майбутньою виплатою. Я не робив фільтрацію за певним тегом, оскільки це обмежить кількість результатів.
Тут обчислюється вік допису. Апвоут відбудеться, якщо до виплати залишилося менше 24 годин і сума до виплати перевищує 100.
5. Перевірка, чи ви вже голосували
function hasVoted(author, permlink, voter)
Ця функція перевіряє допис на наявність вашого логіна у списку тих, хто голосував. Якщо є — пропуск, якщо немає — апвоут.
6. Голосування
function upvotePost(author, permlink, weight = 10000)
Функція голосування. Тут відбувається підпис транзакції вашим постинговим ключем і надсилання в блокчейн.
Зверніть увагу: weight = 10000
. Це сила голосу. 10000 = 100%, 5000 = 50% і т.д.
7. Затримка
function sleep(ms)
Затримка в мілісекундах, прописана як await sleep(15000)
, використовується для запобігання блокуванню сервером при надто частих запитах. Ця пауза відбувається лише після надсилання апвоута.
8. Запуск бота
async function startBot() {
console.log('[' + getCurrentDateTime() + '] Бот запущено.');
while (true) {
await voteTopPosts();
}
}
startBot();
Запуск бота. Фактично цикл роботи бота є безкінечним, поки ви його не вимкнете. До речі, правильно зупиняти роботу скрипта потрібно натисканням комбінації клавіш Ctrl+C
.
Повний код:
const dsteem = require('dsteem');
const client = new dsteem.Client('https://api.steemit.com', {
timeout: 10000,
failoverThreshold: 3
});
const username = ''; // Ім’я користувача в мережі Steem (без символу @)
const postingKey = ''; // Постінговий ключ користувача (секретний ключ для підпису транзакцій)
// Отримати поточну дату та час
function getCurrentDateTime() {
const now = new Date();
const date = now.toLocaleDateString('uk-UA');
const time = now.toLocaleTimeString('uk-UA');
return date + ', ' + time;
}
// Голосувати за топ-100 постів
async function voteTopPosts() {
console.log('[' + getCurrentDateTime() + '] Отримуємо топ-100 постів...');
let discussions = [];
try {
discussions = await client.database.call('get_post_discussions_by_payout', [{ tag: '', limit: 100 }]);
} catch (err) {
console.error('[' + getCurrentDateTime() + '] Помилка отримання постів:', err);
return;
}
const topPosts = discussions;
for (const post of topPosts) {
try {
const postCreated = new Date(post.created + 'Z');
const now = new Date();
const hoursUntilPayout = 168 - (now - postCreated) / (1000 * 60 * 60);
const payout = parseFloat(post.pending_payout_value.split(' ')[0]);
if (hoursUntilPayout <= 24 && payout > 100) {
const voted = await hasVoted(post.author, post.permlink, username);
if (!voted) {
console.log('[' + getCurrentDateTime() + '] Голосуємо за @' + post.author + '/' + post.permlink +
' | Виплата: ' + payout + ' | Залишилось: ' + hoursUntilPayout.toFixed(2) + ' год');
await upvotePost(post.author, post.permlink);
await sleep(15000); // пауза 15 секунд
} else {
console.log('[' + getCurrentDateTime() + '] Уже проголосовано за @' + post.author + '/' + post.permlink);
}
} else {
console.log('[' + getCurrentDateTime() + '] Пропущено пост @' + post.author + '/' + post.permlink +
' — Виплата: ' + payout + ', Залишилось: ' + hoursUntilPayout.toFixed(2) + ' год');
}
} catch (err) {
console.error('[' + getCurrentDateTime() + '] Помилка обробки поста:', err);
}
}
}
// Перевірити, чи вже було голосування
async function hasVoted(author, permlink, voter) {
try {
const content = await client.database.call('get_content', [author, permlink]);
return content.active_votes.some(vote => vote.voter === voter);
} catch (error) {
console.error('[' + getCurrentDateTime() + '] Помилка перевірки голосування:', error);
return false;
}
}
// Здійснити апвоут поста
async function upvotePost(author, permlink, weight = 10000) {
try {
const vote = {
voter: username,
author: author,
permlink: permlink,
weight: weight
};
await client.broadcast.vote(vote, dsteem.PrivateKey.fromString(postingKey));
console.log('[' + getCurrentDateTime() + '] Апвоут відправлено для @' + author + '/' + permlink);
} catch (error) {
console.error('[' + getCurrentDateTime() + '] Помилка під час голосування:', error);
}
}
// Затримка на вказану кількість мілісекунд
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// Запуск бота
async function startBot() {
console.log('[' + getCurrentDateTime() + '] Бот запущено.');
while (true) {
await voteTopPosts();
}
}
startBot();
Бот із цією конфігурацією може бути корисним тільки в тому випадку, якщо ви швидко хочете отримати кураторські винагороди — протягом доби. Але вони будуть невеликими.
Ви можете змінити конфігурацію таким чином, щоби бот голосував за дописи, до виплати за які залишилося... скажімо 144 години (6 діб), а не 24 (п. 4), сума до виплати — 20 або 30 замість 100. Таким чином параметри для голосування будуть більш гнучкі й ви зможете отримати кращі результати.