Steem Bots - Auto Follower Bot [SteemJS & NodeJS] - Begginer Tutorial

in utopian-io •  6 years ago  (edited)

Repository:

https://github.com/steemit/steem-js
steem-bots.png


Repository

What Will I Learn?

  • You will learn how to make auto-follower bot
  • You will learn how to work with getting content from steemit
  • You will learn how to send follow function with steemjs
  • You will learn how to use forEach function to make the same function or actions at the same time for a few tasks
  • You will learn how to make a "spaces" between function to function with timers inside a loop

Requirements

  • You will need NodeJS and the package steemJS

Difficulty

  • Basic

Tutorial Contents

you're going to use nodejs and steemjs to make a bot that loops every 30 minutes to make an auto follow on the last posts that posted in the specific tag that you chose.

Curriculum

The Tutorial

First things first, we need to set up the HTTP server, if you don't understand the code go to NodeJS #1 tutorial and check how it works!

const http = require('http');
const steem = require('steem');
const port = 80; //you can use any other port, like 3000 or something.
const hostIP = "localhost"; //or "127.0.0.1" which is better for you.

const server = http.createServer((req, res) => {
res.statusCode = 200;

res.setHeader('Content-type', 'text-plain');

res.end('Hello World! this is my first project at node.js!');

});

server.listen(port, hostIP, () => {

console.log("Listen to port " + port);

});

your server runs at localhost:80 now.

to run the server use node server or whatever your script name is.
if you have nodemon use nodemon server.

Auto Follow Function

so we need to make the function, call it AutoFollower

function AutoFollower(user, tag, key, limit){

}

user - your account name, the username that going to make the auto-follow.
tag - the tag of the category you're going to follow the other accounts.
key - your posting private key.
limit - limit of the number of posts.

now we need to get the newest posts from your tag.

  steem.api.getDiscussionsByCreated({tag: tag, limit: limit}, function(err, result){
  if(!!err)
  throw err;
  result.forEach(function(row){

  });

so firstly we have the function, this function gets the latest posts that posted with the tag and limit.
example: limit 1, tag: cryptocurrency, it will take the last post that posted on the cryptocurrency tag.
then we check if there is an error we send it to the console and close the app
if not we start a loop for the results.

inside of the loop create the variables

var follower = user;
  var following = row.author;
  var json = JSON.stringify(
  ['follow', {
  follower: follower,
  following: following,
  what: ['blog']
  }]);

follower - the follower username
following - the username that gets the follow
json - the array that gets all of the information for the follow function

now go for a second outside of the loop and create the variable

var count = 0;


and get back in the loop.

now we just need to send the following function

 count+=5;
setTimeout(function(){
steem.broadcast.customJson(key, [], [follower], 'follow', json, function(err, result) {
console.log(err, result);
});}, count*1000);

so it's really simple, first, we adding 5 to the count variable, then we start timeout (timer) with the follow function.
we use the JSON variable that we made, the wif key and the follower name (our account).
and we set the timer to count*1000, it means that the timer is count(=5) seconds.
for example, I have the limit on 5
first, follow - after 5 seconds
second follow - after 10 seconds (but 5 seconds after the first follow)
etc.

now you can do 2 things,
first, you can leave it like that and let it work.
second, you can make a timer for every 30 minutes it will follow 10 users or even more.

so if you want the second way go with me

you need to make a timer for 30 minutes (or hour / less if you want) and run the function in a loop.
go to the end of the function and add this line

setTimeout(function(){AutoFollower(user, tag, key, limit)}, 30*60*1000);


it will make the function "stuck" in a loop because every time it runs it's running the timer again.

example: I run the function once, it will start the timer, when the timer ends it starts the function again and the function starts the timer. so it's a Loop.

and here you've done, just make four variables with the account name, wif key, post limit, and tag and start the function.

var user = "lonelywolf", tag = "cryptocurrency", key = "5AS4D685SA98AW4D89SA165", limit = 3;

AutoFollower(user, tag, key, limit);

it's going to work "forever" until you close the program.

  • Full Code
const http = require('http');
const steem = require('steem');
const port = 80; //you can use any other port, like 3000 or something.
const hostIP = "localhost"; //or "127.0.0.1" which is better for you.

const server = http.createServer((req, res) => {
res.statusCode = 200;

res.setHeader('Content-type', 'text-plain');

res.end('Hello World! this is my first project at node.js!');

});

server.listen(port, hostIP, () => {

console.log("Listen to port " + port);

});

var user = "lonelywolf", tag = "cryptocurrency", key = "****", limit = 3;

AutoFollower(user, tag, key, limit);

function AutoFollower(user, tag, key, limit){
  var count = 0;
  steem.api.getDiscussionsByCreated({tag: tag, limit: limit}, function(err, result){
  if(!!err)
  throw err;
  result.forEach(function(row){
  var follower = user;
  var following = row.author;
  var json = JSON.stringify(
  ['follow', {
  follower: follower,
  following: following,
  what: ['blog']
  }]);
  count+=5;
  setTimeout(function(){
  steem.broadcast.customJson(key, [], [follower], 'follow', json, function(err, result) {
  console.log(err, result);
  });}, count*1000);
  });
  });
  setTimeout(function(){AutoFollower(user, tag, key, limit)}, 30*60*1000);
}
  • Results
Listen to port 80
{ RPCError: plugin exception: Account lonelywolf already submitted a custom JSON operation this block.
  at new RPCError (E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:39:106)
  at E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:74:13
  at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:188:7)
  cause:
  { RPCError: plugin exception:Account lonelywolf already submitted a custom json operation this block.
  at new RPCError (E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:39:106)
  at E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:74:13
  at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:188:7)
  name: 'RPCError',
  code: -32000,
  data:
  { code: 4100000,
  name: 'plugin_exception',
  message: 'plugin exception',
  stack: [Array] } },
  isOperational: true,
  code: -32000,
  data:
  { code: 4100000,
  name: 'plugin_exception',
  message: 'plugin exception',
  stack: [ [Object], [Object], [Object], [Object] ] } } undefined
{ RPCError: plugin exception:Account lonelywolf already submitted a custom json operation this block.
  at new RPCError (E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:39:106)
  at E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:74:13
  at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:188:7)
  cause:
  { RPCError: plugin exception:Account lonelywolf already submitted a custom json operation this block.
  at new RPCError (E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:39:106)
  at E:\web sites\Tutorial 1 - STEEM\node_modules\steem\lib\api\transports\http.js:74:13
  at <anonymous>
  at process._tickCallback (internal/process/next_tick.js:188:7)
  name: 'RPCError',
  code: -32000,
  data:
  { code: 4100000,
  name: 'plugin_exception',
  message: 'plugin exception',
  stack: [Array] } },
  isOperational: true,
  code: -32000,
  data:
  { code: 4100000,
  name: 'plugin_exception',
  message: 'plugin exception',
  stack: [ [Object], [Object], [Object], [Object] ] } } undefined
null { id: '060a2b40e64a06929fccebba18996f31626895fc',
  block_num: 26773113,
  trx_num: 13,
  expired: false,
  ref_block_num: 34407,
  ref_block_prefix: 961633877,
  expiration: '2018-10-13T13:54:30',
  operations: [ [ 'custom_json', [Object] ] ],
  extensions: [],
  signatures:
  [ '2078744fa2df0bce7541e1a0e23ec754166a33449b8c456f9c41b893fc7e1f5505449064eedfd40d2c250aa34bec886710c3baff03c7716602e4939e052fc3a828' ] }
[nodemon] restarting due to changes...
[nodemon] starting `node server server.js`
Listen to port 80
null { id: '53527546cb8351724474120b1962e0f1d325b0a3',
  block_num: 26773128,
  trx_num: 9,
  expired: false,
  ref_block_num: 34422,
  ref_block_prefix: 3768848869,
  expiration: '2018-10-13T13:55:15',
  operations: [ [ 'custom_json', [Object] ] ],
  extensions: [],
  signatures:
  [ '203fa180faa1c5efea17f1f9df0411dadb678f33068d291bdfaf05289ac0f671e7199311015f2d38b6889966bcf82030a42b1db7494996d4a055c6ce77f04587ab' ] }
null { id: '3bc7090516c402c8ed561e74efdf964f827f4a89',
  block_num: 26773130,
  trx_num: 7,
  expired: false,
  ref_block_num: 34424,
  ref_block_prefix: 2991298112,
  expiration: '2018-10-13T13:55:21',
  operations: [ [ 'custom_json', [Object] ] ],
  extensions: [],
  signatures:
  [ '1f0c878317a7c878444da41254ee8d5d88cb68d84bbfe28bfb8e53ebc094e46c983297ddcf050d04e30b2dfa7a0c9bdaacd3bf75629fd1848708063c52e614afdd' ] }
null { id: '5bfd069f20d572a8f19b86a269ef4ea29b61cbc2',
  block_num: 26773132,
  trx_num: 0,
  expired: false,
  ref_block_num: 34426,
  ref_block_prefix: 4171029757,
  expiration: '2018-10-13T13:55:27',
  operations: [ [ 'custom_json', [Object] ] ],
  extensions: [],
  signatures:
  [ '1f0ef1c0b56e85a9cdadfcded2f25305f29a8b35b629084566ee276293ae2583d134b0736ad63892c2bfdc2b62749f329bfe20bf2db33cfaf82e9df7136615b5e8' ] }
[nodemon] restarting due to changes...
[nodemon] starting `node server server.js`
Listen to port 80
null { id: '4007bd875ca1794aead4cfe3bfba5175702e6ef5',
  block_num: 26773351,
  trx_num: 10,
  expired: false,
  ref_block_num: 34639,
  ref_block_prefix: 2477891887,
  expiration: '2018-10-13T14:06:24',
  operations: [ [ 'custom_json', [Object] ] ],
  extensions: [],
  signatures:
  [ '200cada2c83eb688a2ac8421ec2dd51f58ac7f3bd89aea1b432ac44a586aec352c5ba398c343c5ddda973502db901ce1cfb50ea044e1d819398f8f788da0fd964c' ] }
null { id: '2aa5ca636d62e4838da1577dcb765bdcbbfa9ba1',
  block_num: 26773353,
  trx_num: 4,
  expired: false,
  ref_block_num: 34642,
  ref_block_prefix: 967637030,
  expiration: '2018-10-13T14:06:30',
  operations: [ [ 'custom_json', [Object] ] ],
  extensions: [],
  signatures:
  [ '205dfd7082d7653c55fde4bdb16f094be9f6cea1af36b0ce9f8fd183673ad98b257a2be76b7aa784855d2867625be05c02508706987c88162821d6bf8862cf6c75' ] }
null { id: 'c040ed08a57ae2c818ba3f15073281d02fc4a605',
  block_num: 26773354,
  trx_num: 31,
  expired: false,
  ref_block_num: 34643,
  ref_block_prefix: 3131168984,
  expiration: '2018-10-13T14:06:33',
  operations: [ [ 'custom_json', [Object] ] ],
  extensions: [],
  signatures:
  [ '1f0142ca00c3bb1e88998987d786b80e4b8e0dc694194a81a12abc8b8ae3d1e73c22339420bb185c1990caeb5868b30ee6e2c706a1445042a28b203d8c700d7331' ] }

everything after null is the change in the block, that means it's the follow function works successfully.

Proof of Work Done

have a good day, we're done for this tutorial!
this series will continue at the next week with more tutorials and with more content!

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Thank you for your contribution @lonelywolf.
After an analysis of your tutorial we suggest the following:

  • We suggest you only put the code in the tutorial, putting images from your editor does not help the reader and increases your tutorial unnecessarily.

  • Be more careful when building your tutorial text, it is good to explain in detail and also apply a bit of theory.

  • Your full code is already in github, we suggest you not replicate the whole code in your tutorial.

  • Please ident your code, make it easier for users to read.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.


Need help? Write a ticket on https://support.utopian.io/.
Chat with us on Discord.
[utopian-moderator]

Thank you for your review, @portugalcoin!

So far this week you've reviewed 7 contributions. Keep up the good work!

Your PRIVATE POSTING KEY has been compromised. Any malicious person can POST, COMMENT, or VOTE from your account. Please change your MASTER PASSWORD as soon as possible.

thanks a lot for those bots that take care about that.

Hello @lonelywolf,

I just found this key: 5JHmrUYm************************************qUEjq2zJ

This is your PRIVATE POSTING KEY.

Use this link to change your password: https://steemit.com/@lonelywolf/password

Your PRIVATE POSTING KEY has been compromised. Any malicious person can POST, COMMENT, or VOTE from your account. Please change your MASTER PASSWORD as soon as possible.

Hello @lonelywolf,

I just found this key: 5JHmrUYm************************************qUEjq2zJ

This is your PRIVATE POSTING KEY.

Use this link to change your password: https://steemit.com/@lonelywolf/password

Hi @lonelywolf!

Your post was upvoted by @steem-ua, new Steem dApp, using UserAuthority for algorithmic post curation!
Your post is eligible for our upvote, thanks to our collaboration with @utopian-io!
Feel free to join our @steem-ua Discord server

Hey, @lonelywolf!

Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Get higher incentives and support Utopian.io!
Simply set @utopian.pay as a 5% (or higher) payout beneficiary on your contribution post (via SteemPlus or Steeditor).

Want to chat? Join us on Discord https://discord.gg/h52nFrV.

Vote for Utopian Witness!