TUTORIAL - Beginner friendly - Build your first steem bot in Javascript - 30minutes

in #utopian-io ā€¢ 6 years ago (edited)

JS-BOT-PNG.png

Hey everyone šŸ‘‹, you might have noticed Iā€™ve been learning about the Steem-js library and building a couple of projects. I wanted to create my first tutorial to show you how to create a simple Steem bot in Javascript. There is a lot we could do with a bot but for the purpose of this tutorial and to keep it beginner friendly our bot will be fairly simple.

The completed bot code is here - I know some people find it easier to see everything in one block and follow along that way. ā¬…ļø

Outline

We will create an auto-voting bot, our bot will automatically upvote posts from our selected list of usernames. Imagine you have new friends joining the platform, and you want to encourage them with upvotes but youā€™re too busy to check Steemit regularly.

What you need

  • A plain text editor (I use atom.io )
  • Your private posting key - This is found in your wallet on the permissions tab on steemit.com, click ā€˜show private keyā€™ (remember to keep this safe). This is what allows the bot to vote for you

Goals

  • specify a list of usernames (our friends)
  • connect to the Steem-js API
  • check when a new post is posted to the Steem network
  • check if the post belongs to any of our friends
  • send a vote to that post

Step 1 - setup šŸ’»

For this tutorial our bot will run in the web browser, a more effective way to use this bot would be on the command-line but weā€™ll save that for another post.

Weā€™re going to set up a blank HTML file and link to the steem.js library. The library does most of the work, talking to the Steem network and means we have to write very little code ourselves.

<html>
    <head>
    <script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>
        <script></script>
    </head>
    <body></body>
</html>

Go ahead and save this file as bot-tutorial.html. You can open this up in your browser although youā€™ll just see a white screen for now. Looking at the code you can see we have added the basic structure of a html page. All pages are made up on the , and tags. Weā€™ve linked to the steemjs library file with a script tag. We also have our own tags to work with. This is where our javascript code will go.

Let's try testing everything is good to go. Add a console message to your script tag like so.

    <script>
        console.log(ā€˜hello, is this workingā€™)
    </script>

Now open up the developer tools in your browser and move to the console.

  • Chrome - View > Developer > Javascript Console
  • FireFox - Tools > Web Developer > Browser Console
  • Safari - Develop (turn on in advanced options - Safari prefrences) > Show Javascript Console
  • IE/Edge/Windows šŸ¤·ā€ā™‚ļø

Screen Shot 2018-01-08 at 17.14.50.png

If youā€™ve got the message above, let's keep moving.

Step 2 - create friends list šŸ‘«

Weā€™ll store a list of friends in our code to start, we can use these names later to decide if to vote or not.

In javascript lists of information are called an Array, they are specified with the square brackets. Text needs to be represented with single or double quotes around it and itā€™s a list so we separate the names with commas.

Add this line below our console.log from above.

const FRIEND_LIST = ['sam', 'fred', 'sarah', 'lucy']

const Is a store of information that is constant, so our list of friends canā€™t/wonā€™t change once our bot is running.

Step 3 - Connect to the Steem-js API šŸ™Œ

Here comes the fun part. We want to connect to the steem network and check all new transactions. Each block on the steem blockchain holds transactions, these can be anything transfers, votes, comments, profile updates to name just a few. Once we connect every couple of seconds weā€™ll be sent new data from the blockchain.

First, we need to set the URL where we receive information (currently the CDN hosted teemA-js tries to connect to an out of date URL *as of 6th Jan)

Whenever we interact with the Ateem-js library weā€™ll specify steem.api. and then the action weā€™re taking, most actions also need some extra information (these are called arguments), in this case, itā€™s the URL we want to connect to.

steem.api.setOptions({ url: 'wss://rpc.buildteam.io' });

The real magic is this next line.

steem.api.streamTransactions('headā€™,(error, result) => {});

This time weā€™re using the streamTransactions action to request the transactions from each block as theyā€™re processed. weā€™re then taking the data (the error and the result and sending them into our own action. Between those curly baskets {} we can check for an error or see the result. Let's try that.

steem.api.streamTransactions('headā€™,(error, result) => {
    console.log(error, result)
});

as new transactions come In weā€™ll see each one in the browser console. It might look a bit funky, you also might get a lot, donā€™t worry weā€™ll narrow it down in just a second.

{ref_block_num: 60613, ref_block_prefix: 233123265, expiration: "2018-01-08T17:34:44", operations: Array(1), extensions: Array(0), ā€¦}

Okay looking at above we have, Block Number, Operations, extensions etc. What weā€™re looking at is a Javascript Object, itā€™s a way to store a group of information together. Weā€™re interested in the Operations part. To make life easier for ourselves lets store the relevant information with better names. Click the little down arrows to see inside to the information we want.

Screen Shot 2018-01-08 at 17.37.25.png

steem.api.streamTransactions('headā€™,(error, result) => {
  let txType = result.operations[0][0]
  let txData = result.operations[0][1]
    console.log(txType)
});

We creating two variables here to store our information. transaction type eg vote, comment etc and transaction data this is everything else relevant so for a comment it might be who commented and on what post etc. We first take the result then specify we want just the operations part then because operations is an Array we select the parts we want with square brackets.

Now instead of seeing all of the information coming through, weā€™ll just see the type. Try it out. For our bot weā€™re interested in ā€˜commentsā€™, this is because there is actually not a type of post or blog, all blogs are classified as comments on the Steem network, its just that blog posts arenā€™t replying to anyone.

step 4 - checking friends names šŸ“

we need to create a way to check if the names we get from the blockchain match those in our list of friends. Letā€™s make a function. Functions allow us to create blocks of code we can reuse over and over.

function isFriend(name){
  return (FRIEND_LIST.indexOf(name) > -1);
}

Out function takes one piece of data ā€˜nameā€™ and itā€™s going to return us a yes/no or really a true/false answer. Whatā€™s happening here is we are taking our FRIEND_LIST and looking for the index( the position ) of the name we entered. if our friend is is the list it will say 1 or 3 for example if not it says -1. checking if the answer is > -1 gives us our true/false for friends. Try it out.

function isFriend(name){
  return (FRIEND_LIST.indexOf(name) > -1);
}
isFriend(ā€˜samā€™)
// yes
isFriend(ā€˜lucyā€™)
// yes
isFriend(ā€˜bobā€™)
// no

next, weā€™ll create another function to check the transaction data. Weā€™re looking to see if the author is our friend (with the function above), but we also need to check that the parent_author is empty, if itā€™s empty we know this is a blog post and not a comment on someone else post.

function checkAuthor(txData){
  if (txData.parent_author == '' &&  isFriend(txData.author)){
        console.log(ā€˜our friend posted a blog post!!!ā€™)
  }
}

This one is a little more involved. we are checking the transaction data which looks like this.

author: ā€œnamehereā€
body: "That is a blast. It has an amazing potential!ā†µI will definitely participate in it!"
json_metadata : "{"tags":["crypto"],"app":"steemit/0.1"}"
parent_author: ""
parent_permlink: ""
permlink : ā€œlongā€”name-like-thisproject-20180108t173707137z"
title: ā€œawesome post titleā€

you access this information with dot notation so if we want the author it is txData.author itā€™s called txData because thatā€™s what we specified in our function it could be called anything.

this time weā€™re checking that this is a blog post and not just a comment with txData.parent_author == '' thatā€™s checking the parent_author is empty and using our function to check if the txData.author is in our friend's list.

Going back to out Steem transaction function we can combine these together. Weā€™ll check the transaction type is equal to comment and then weā€™ll check the author.

steem.api.streamTransactions('head', (err, result) => {
  console.log(result)
  let txType = result.operations[0][0]
  let txData = result.operations[0][1]
     if(txType == 'comment') {
        checkAuthor(txData)
     } });

Looking good. With all this together weā€™ll get a message in the browser console every time any of our friend's posts!

Step 5 - Sending Votes šŸ‘

Okay, weā€™re super close! Final Steps!

First up let's make a couple more constants to store information. You can do this at the top of your script, right by your friend's list.

const ACCOUNT_NAME = ā€˜yourusernamehereā€™
const ACCOUNT_POSTING_KEY = ā€˜yourprivatepostingkeyhereā€™

Fill in this information with your username and private posting key.

function sendVote(author, permlink){}

Let's create another function, this time the data we need is the author and the permlink, this is going to be which author and what post weā€™re voting on.

function sendVote(author, permlink){
   steem.broadcast.vote(ACCOUNT_POSTING_KEY, ACCOUNT_NAME, author, permlink, 10000, function(err, result) {
        console.log(result);
   });
}

Here you can see weā€™re doing a ā€˜steem.broadcastā€™ the data we need to send is the posting key, account name, the author, the link and a voting weight. Note the voting weight does not use percentages so 10000 is the same as 100%.

All thatā€™s left to do is using this function inside our check author function. letā€™s edit that now.

function checkAuthor(txData){
  if (txData.parent_author == '' &&  isFriend(txData.author)){
    sendVote(txData.author, txData.permlink)
  }
}

Update the function to add our sendVote function instead of just a message. Weā€™re taking the data from the transaction and using it in our send vote function.

thatā€™s it - run this code in your browser and whenever your friend postā€™s it will automatically upvote their post. šŸ‘

Here's the full code

Thereā€™s a lot more we can do with bots and the Steem API but I hope this has been an interesting look at a simple bot.

post note - are bots a good idea? do bots devalue the Steemit platform? really interested to hear your thoughts on this. My take is that any ā€˜bad guysā€™ already know how to do this so showing you isnā€™t such a big deal. Remember to consider weā€™re hear to talk to humans, not robots. Use your new skills wisely



Posted on Utopian.io - Rewarding Open Source Contributors

Sort: Ā 

Thank you for the contribution. It has been approved.

You can contact us on Discord.
[utopian-moderator]

Awesome thanks for approving this tutorial it so quickly! āš”ļøšŸ‘Š

This is pretty cool! I think I'm following just enough people to vote for myself,but I will co sider this! So well explained!

šŸ‘ Thanks for taking a look. It's not the best bot concept, to be honest, but it's the simplest one I could think up that might still have some real use case. Hopefully, it shows that you don't need a crazy amount of code or knowledge to make a šŸ¤– do some work for you.

Great stuff Sam! Useful especially now that @steemvoter stopped working and won't work for at least 1 week. Thanks for this.

Great tutorial. I will use it to write a bot which upvotes all sambillingham posts, so I do not have to do it manually. Will save me lots of time ;) Thanks.

Haha too kind, thanks for checking it out Jo!

Thanks for this info. I think it's still helpful even now.

I'm clearly late to this party, but I wanted to thank you for this great tutorial! I'll go find a more recent post from you to upvote :)

Informative post

thanks for this post I was actually looking for this

Hey @sambillingham I am @utopian-io. I have just upvoted you!

Achievements

  • You have less than 500 followers. Just gave you a gift to help you succeed!
  • Seems like you contribute quite often. AMAZING!

Suggestions

  • Contribute more often to get higher and higher rewards. I wish to see you often!
  • Work on your followers to increase the votes/rewards. I follow what humans do and my vote is mainly based on that. Good luck!

Get Noticed!

  • Did you know project owners can manually vote with their own voting power or by voting power delegated to their projects? Ask the project owner to review your contributions!

Community-Driven Witness!

I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!

mooncryption-utopian-witness-gif

Up-vote this comment to grow my power and help Open Source contributions like this one. Want to chat? Join me on Discord https://discord.gg/Pc8HG9x

For this particular version of js file can you post the code for post comments?


var parentAuthor = 'author1';
var parentPermlink = 'permlink;
var commentPermlink = steem.formatter.commentPermlink(parentAuthor, parentPermlink);
var postTitle = WELCOME_COMMENT_TITLE;
var postBody = WELCOME_COMMENT_BODY;

steem.broadcast.comment(ACCOUNT_WIF, parentAuthor, parentPermlink, ACCOUNT_NAME,
commentPermlink, postTitle, postBody,
{"tags":["tag1"]},
function(err, result) {
console.log(result);
});

The above code doesn't seem to work and the version specific changes are not documented well enough I think.

Hey @gokulnk, can you be a little more clear so I can help you out?

  • Where is this code from? (it's not this tutorial)
  • What do you mean by 'code doesn't work' - what error messages are you getting, what is happening?
  • What are you wanting to do?
  • Can you post your full code somewhere?

The code you have given in your sample works perfectly.

I was just trying to build on it to add comments to a post.

I keep getting the following error.

"Expected version 128, instead got 149"

Please let me know if you were able to post comments through the code.

okay thanks for clarifying, it's 100% possible to send comments through code.

See this broadcast function - https://github.com/code-with-sam/steem-versary-bot/blob/master/bot.js#L183

notice the operations array on line 150 - https://github.com/code-with-sam/steem-versary-bot/blob/master/bot.js#L150

Looks like I am having issues with all the broadcast functions. stream functions are working fine though.

Let me know if we can discuss this in steemchat.

perhaps you are trying to do steem.api.broadcast() when it should be steem.broadcast() ?

Also check you're not redefining steem anywhere?

p.s post your full code as a gist!

For ACCOUNT_WIF I was using the actual password and not the posting key. After changing that it is working well. Since it was WIF related issue other calls were working and only those where WIF was involved were throwing the error.

I wish the message was little more verbose. It could have saved me a lot of time :P

Thanks for your inputs.

Coin Marketplace

STEEM 0.29
TRX 0.12
JST 0.033
BTC 62559.43
ETH 3092.10
USDT 1.00
SBD 3.86