Bots In Python #2 | Removing, Improving And Adding Commands | DiscordSteem | Part #2

in #utopian-io6 years ago (edited)


Hello Everyone! Welcome to the second part of DiscordSteem series in which we are creating a discord bot that gets information about Steem Blockchain using Beem and then displays it on the Discord server. In the last part, we created four functions. One of those functions was !rep which we are going to be removing in this tutorial. Instead, we are going to be creating a function called !info which will display all the information of the account like how many accounts is the account following and how many followers does the account have. We will also be improving the comments, feeds and blog command. Instead of bot leaving multiple embed messages, we will be changing it to a single embed message. We are going to be creating one new command in this tutorial and that is going to be !info. This command will give you some valuable information about any user steem user you want.

Repository

Other Related Repositories

What Will I Learn?

In this tutorial, you will learn how you can use Discordpy to interact with Discord and get messages. We are also going to be learning how we can use the information/commands in the messages to perform actions and to get information using Beem. This information will then be sent in the Discord server and of course this all will be done in Python.

Requirements

In order to follow along with this tutorial you will need to have these things installed.

  • Python 3.6
  • Beem
  • Discord.py

Difficulty

  • Intermediate

Tutorial Contents

Improving Blog, Feed And Comments Commands

Allowing Users To Assign The Amount Of Posts/Comments

In the last post, we created three commands. Each command displayed posts, the blog command displayed last 5 blog posts of the user, the feed command showed feed and comments command showed the last comments. We will make some changes and improve this. The first change that we are going to be making is that we will allow user to decide the number of posts/comments they want. We will do that by assigning a optional parameter in the function. Let's do that for blog command first. Here's how the command looks like at the moment.

@bot.command(pass_context=True)
async def blog(ctx, username):
  acc = Account(username.lower())
  for post in acc.blog_history(limit=5, reblogs=False):https://s22.postimg.cc/smdvuhlip/Screenshot_from_2018-08-21_11-41-31.png
    embed = discord.Embed(title=(post["title"]), color=(0x00ff00))
    await bot.say(embed=embed)

Change it to something like this.

@bot.command(pass_context=True)
async def blog(ctx, username, amount=5):
  acc = Account(username.lower())
  for post in acc.blog_history(limit=amount, reblogs=False):
    embed = discord.Embed(title=(post["title"]), color=(0x00ff00))
    await bot.say(embed=embed)

Here are the changes that we have made. Firstly, we have added another parameter to the function which is called "amount" and have set it to 5. With this, if user has assigned the variable then it will not be 5 but it will change to the number which user has assigned. If user hasn't assigned this variable then it will set to 5 as default. In the blog_history, we have set the limit to "amount" variable that we just created so users are able to control the number of posts they want. Let's see it working.


As you can see it is pretty simple to do this and I think that you will be easily able to do this for other two commands. The procedure to allow users to change the amount of posts/comments for other two commands is exactly the same so I won't be teaching it. Take this as little challenge and do it by yourself.

Sending All The Posts In One Message

So we know that whenever user requests 5 blog posts of someone. Our bot sends 5 messages, each containing the title of the post. We are going to be changing that because bot leaving 5 messages at a time just creates a mess. The messages could be interrupted in servers which are very active. To create a single message with all the posts, we will need to create a embed message before the for loop. In the for loop we will be adding fields to the embed message (you will see what I mean). After the for loop is completed, we will send the message to the server. You will understand better when I do it.
Here's what our blog command looks like right now.

@bot.command(pass_context=True)
async def blog(ctx, username, amount=5):
  acc = Account(username.lower())
  for post in acc.blog_history(limit=amount, reblogs=False):
    embed = discord.Embed(title=(post["title"]), color=(0x00ff00))
    await bot.say(embed=embed)

The first step will be to put the embed variable outside the for loop. We will also change the title of the embed message and add description. After putting the "embed" variable outside the for loop, the command will look like this. I have also changed the title and added the description.

@bot.command(pass_context=True)
async def blog(ctx, username, amount=5):
  acc = Account(username.lower())
  embed = discord.Embed(title=("DiscordSteem"), description=("Last %s Posts Of %s" % (amount, username)),color=(0x00ff00))
  for post in acc.blog_history(limit=amount, reblogs=False):
    await bot.say(embed=embed)

Delete the "await bot.say(embed=embed)" line from the for loop too. Replace it with embed.add_field(name=(post["title"]), inline=True). Then after the for loop, we are going to ask the bot to send the message to the server. Here's what our command will look like now.

@bot.command(pass_context=True)
async def blog(ctx, username, amount=5):
  acc = Account(username.lower())
  embed = discord.Embed(title=("DiscordSteem"), description=("Last %s Posts Of %s" % (amount, username)), color=(0x00ff00))
  for post in acc.blog_history(limit=amount, reblogs=False):
    embed.add_field(name=(post["title"]), value=("By " + post["author"]))
  await bot.say(embed=embed)

You can see that await bot.say(embed=embed) is outside the for loop. I have also added the value to the field because it is necessary. We can also make it more professional by adding a thumbnail to the embed message. Under the "embed" variable, type embed.set_thumbnail(url=(acc.profile["profile_image"])) and this will fetch the profile picture of the account and then use it as a thumbnail. Let's check how our function looks like right now. Cool right?
Screenshot from 2018-08-21 14-00-47.png
Since this is a little more complex than previous change, I will help you do it for other two commands as well. Let's move on to the feed command which is favorite command because of it uniqueness. Change the feed command's code to something like this.

@bot.command(pass_context=True)
async def feed(ctx, username, amount=5):
  acc = Account(username.lower())
  embed = discord.Embed(title=("DiscordSteem"), description=("This is the feed of %s" % (username)), color=(0x00ff00))
  embed.set_thumbnail(url=(acc.profile["profile_image"]))
  for post in acc.feed_history(limit=amount):
    embed.add_field(name=(post["title"]), value=("By " + post["author"]))
  await bot.say(embed=embed)

You can see that most of the code is same. The only difference is the description of the embed message. Let's now move towards the last command which is comments one. Change the code of this command to this.

@bot.command(pass_context=True)
async def comments(ctx, username, amount=5):
  acc = Account(username.lower())
  embed = discord.Embed(title=("DiscordSteem"), description=("These are last %s comments of %s" % (amount, username)), color=(0x00ff00))
  embed.set_thumbnail(url=(acc.profile["profile_image"]))
  for post in acc.comment_history(limit=amount):
    embed.add_field(name=(post["title"]), value=("By " + post["author"]))
  await bot.say(embed=embed)   

Now all the commands should be sending one message instead of numerous messages. Users are also able to select the number of posts or comments they want. Now it's the time to create new command.

Creating Info Command

Now we will be creating !info <user> command. When we will use this command we will be able to get good amount of information about the user. This information will include the number of account the user is following, the number of accounts that are following the user, reputation of the user, profile picture of the user, "about" of the user, number of posts, steem balance, sbd balance and number of witnesses the user has voted for. Since this command will show the reputation of the user, there's no point to have another command for that so delete the rep function that we made in the previous tutorial. This sure is a lot of information so let's get started with building with command.

The first is surely going to be @bot.command(pass_context=True). I have already explained in the previous part what is meant by this. The second line will be async def info(ctx, username):. In this we are creating a function with the name info and it has two parameters. The first one is "ctx" which stands for context (in our case it is !info) and the second parameter is "username" which is just going to be Steemit user. The third line is going to be acc = Account(username.lower()) which is also explained in the previous part. The fourth is going to be embed = discord.Embed(title=(username), description=(acc.profile["about"]), color=(0x00ff00)). In this code we are creating a embed message of which the title is going to be the username and description is going to be "about" of user which is present inside the profile. I have also assigned color which is in form of hex code and the one which I have used is green color. The fifth line is going to be embed.set_thumbnail(url=(acc.profile["profile_image"])), with this we are setting the thumbnail like done in other commands. Here's how our command looks like until now.

@bot.command(pass_context=True)
async def info(ctx, username):
  acc = Account(username.lower())
  embed = discord.Embed(title=(username), description=("Information"), color=(0x00ff00))
  embed.set_thumbnail(url=(acc.profile["profile_image"]))

Till now we have created this command very similar to other commands. Now is the time to add some fields with the relevant information. The first field that we are going to be adding is going to be for reputation since we have deleted the previous command for this. Under the last line type embed.add_field(name=("Reputation"), value=(int(acc["reputation"]))). We are adding a new field to the embed message in this code with the name "Reputation" and the value is going to be the reputation of the account. You must have notice that the value is inside int() this is because I want only the integer value this time. The second field is going to look something like this embed.add_field(name=("Followers"), value=(len(acc.get_followers()))). The name of this field is "Followers" and the value is going to be the number of followers. To get the list of all followers we type acc.get_followers() and it will return us a list of all the followers. After that, we have counted the followers using the len() function. The third field is very similar to last one, it is embed.add_field(name=("Accounts Following"), value=(len(acc.get_following()))). I don't think I need to explain this one.

The fourth one is embed.add_field(name=("Number Of Posts"), value=(acc["post_count"])). The name of the field is going to be "Number Of Posts" and the value is going to be the post_count which is present inside the account data. The fifth field is going to be the embed.add_field(name=("STEEM Balance"), value=(acc["balance"])) . You already know by now what is happening :p. The sixth is also very similar embed.add_field(name=("SBD Balance"), value=(acc["sbd_balance"])). The last field is embed.add_field(name=("Witnesses Voted"), value=(acc["witnesses_voted_for"])). At the last type await bot.say(embed=embed). You can see those were a lot fields. Here's what our command looks like right now.

@bot.command(pass_context=True)
async def info(ctx, username):
  acc = Account(username.lower())
  embed = discord.Embed(title=(username), description=(acc.profile["about"]), color=(0x00ff00))
  embed.set_thumbnail(url=(acc.profile["profile_image"]))
  embed.add_field(name=("Reputation"), value=(int(acc["reputation"])))
  embed.add_field(name=("Followers"), value=(len(acc.get_followers())))
  embed.add_field(name=("Accounts Following"), value=(len(acc.get_following())))
  embed.add_field(name=("Number Of Posts"), value=(acc["post_count"]))
  embed.add_field(name=("STEEM Balance"), value=(acc["balance"]))
  embed.add_field(name=("SBD Balance"), value=(acc["sbd_balance"]))
  embed.add_field(name=("Witnesses Voted"), value=(acc["witnesses_voted_for"]))
  await bot.say(embed=embed)   

Here's how it looks likes whenever we use the commands. I know it's not perfect but we will be improving it in the future. I think this is a good command to quickly check out someones information while you are chatting on Discord.
Screenshot from 2018-08-21 14-00-47.png

Final Thoughts

I know we weren't as productive in this part as we were in the last one but I think you learned some very valuable things, like how you can get different type of information about a user or how to work your way around a problem. Thank you reading this tutorial, see ya!

Curriculum

Here's a list of tutorials that are related to building bots in Python.

Proof of Work Done

Note: There are some changes in the code of the repository. The name of the file is changed from "bot.py" to "DiscordSteem.py". I have not added the token to my code in code and to be able to use the code you must add the token of your bot. Thanks.

Sort:  

Thank you for your contribution.

  • Improve the structure of your tutorial, give spaces between paragraphs. Paragraphs very extensive it gets annoying to read.
  • Please put comments in your code, it is easier to interpret what you are doing in the code.For example:
//Description bot commands
@bot.command(pass_context=True)
async def blog(ctx, username, amount=5):
  acc = Account(username.lower())
//Description of the cycle
  for post in acc.blog_history(limit=amount, reblogs=False):
    embed = discord.Embed(title=(post["title"]), color=(0x00ff00))
    await bot.say(embed=embed)


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 18 contributions. Keep up the good work!

Thanks for the review. I will try my best to add more comments and make paragraphs shorter next time!

Hi @rodus! We are @steem-ua, a new Steem dApp, computing UserAuthority for all accounts on Steem. We are currently in test modus upvoting quality Utopian-io contributions! Nice work!

Congratulations! Your post has been selected as a daily Steemit truffle! It is listed on rank 14 of all contributions awarded today. You can find the TOP DAILY TRUFFLE PICKS HERE.

I upvoted your contribution because to my mind your post is at least 20 SBD worth and should receive 137 votes. It's now up to the lovely Steemit community to make this come true.

I am TrufflePig, an Artificial Intelligence Bot that helps minnows and content curators using Machine Learning. If you are curious how I select content, you can find an explanation here!

Have a nice day and sincerely yours,
trufflepig
TrufflePig

Coin Marketplace

STEEM 0.16
TRX 0.15
JST 0.028
SBD 2.31