Бот для пасивного заробітку в Steemit (частина 2)steemCreated with Sketch.

in Ukraine on Steemlast month

До написання цього допису мене мотивував власний допис, в якому я навів приклад бота, який працює з сайтом 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.

2025-06-13_185359.png

Повний код:

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. Таким чином параметри для голосування будуть більш гнучкі й ви зможете отримати кращі результати.