TUTORIAL - Beginner friendly - Build your first steem bot in Javascript - 30minutes
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 š¤·āāļø
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.
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. š
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
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
Suggestions
Get Noticed!
Community-Driven Witness!
I am the first and only Steem Community-Driven Witness. Participate on Discord. Lets GROW TOGETHER!
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?
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 besteem.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.