Part 16: How To Analyse A User's Vote History In A Specific Time Period Using Steem-Python
![steem-python.png](https://steemitimages.com/640x0/https://res.cloudinary.com/hpiynhbhq/image/upload/v1515886103/kmzfcpvtzuwhvqhgpyjp.png)
This tutorial is part of a series where we explain different aspects of programming with steem-python
. Links to the other tutorials can be found in the curriculum section below. In part 9 of this series we learned how to calculate the total rewards of a post and in this tutorial we will learn how to estimate the curation rewards of a post!
What will I learn
- How to sort an account's history
- How to only analyse the last
N
days - How to use a
namedtuple
- How to format output nicely
Requirements
- Python3.6
steem-python
Difficulty
- Basic
Tutorial
If you find it easier to follow along this way you can get the entire code for this tutorial from here, where I have split everything up into the relevant sections.
Filtering an account's history
Instead of streaming and filtering the blockchain we can also do this for an account's history as we did in part 12. To do this we used the function history_reverse()
, which streams an account's history in reverse chronological order. Filtering this is done the same was as filtering the blockchain, so for example if we want to filter an account's history and see what posts that account voted on, we can do the following
account = "utopian-io"
for vote in Account(account).history_reverse(filter_by="vote"):
if vote["voter"] == account:
# DO SOMETHNIG
Limiting history to a certain period
Just like when we analysed the rewards, we don't want to go through an account's entire history, so we should limit it to a certain time period. To do this we can use datetime
's timedelta()
function. Using timedelta()
we can easily define a time period, so for example five days would be timedelta(days=5)
and five weeks would be timedelta(weeks=5)
. For now let's limit it to one hour. So to get all posts that the specified account voted on in the last day we can do the following
import datetime
from dateutil.parser import parse
current_time = datetime.datetime.now()
time_period = datetime.timedelta(hours=1)
for vote in Account(account).history_reverse(filter_by="vote"):
if vote["voter"] == account:
time_voted = parse(vote["timestamp"])
if current_time - time_voted < time_period:
# DO SOMETHING
else:
break
In part 12 we could just use the time_elapsed()
function on a Post
function to see if the time period had already passed, but this time we use dateutil.parser
's parse
function to easily get the time a vote was made.
Creating a namedtuple
Now we can limit the account's voting history to a certain period we can decide what to do with it. For example, you could want to print the post's author, the title of the post and its pending payout. A nice way to do this is to create a User
object with all this information so we can easily print this afterwards. To do this we need to define what our User
object will look like before we do this, like so
from collections import namedtuple
User = namedtuple("User", ["name", "post", "pending"])
Using this we can then create a list of these objects as follows
users = []
for vote in Account(account).history_reverse(filter_by="vote"):
if vote["voter"] == account:
time_voted = parse(vote["timestamp"])
if current_time - time_voted < time_period:
permlink = "@{}/{}".format(vote["author"], vote["permlink"])
post = Post(permlink)
if post.is_main_post():
# Create list of User objects
user = User(post["author"], post["title"],
Amount(post["pending_payout_value"]).amount)
users.append(user)
else:
break
Printing everything nicely
Once we have our list of User
objects we can print them out in whatever format we want. For example, I want to print everything like this: <author> - <title> - $<pending payout>
, where the title is truncated, and print the total pending payout at the end. I also want everything to be spaced nicely, so everything lines up and it's easier to read. To do this I can use the following code
total_pending = sum([user.pending for user in users])
width = 40
for user in users:
print("{0:16} - {1:43} - ${2}".format(
user.name, user.post[:width] + (user.post[width:] and "..."),
user.pending))
print("Total pending payout: ${}".format(total_pending))
where we specify the index of the variable and the width with {<index>:<width>}
. We also truncate the title by slicing it. At the time of writing this tutorial this had the following output
aldianrony1 - My idea. Add the function of who has vis... - $7.42
arie.steem - Gpredict - Make It New Module & Setting ... - $46.869
darewealth - Adding incognito Tab to Lucid Browser - $7.41
redart - Geogebra Dynamic Mathematics Turkish Vid... - $43.307
fabiyamada - STEEM PLUS - New view styles for the fee... - $155.179
buckydurddle - VCV Rack - JW Module Full Scope - $51.834
miniature-tiger - Analysis of @steemit Account Powerdown - $112.097
raycoms - Minecolonies & The Quality of Playing - ... - $238.65
tobias-g - Steemgigs spotlight (User recognition ar... - $27.083
justyy - Adding `Stats` Class to PHP Client of Ut... - $154.088
netuoso - [Steem Examples] Steem Price Rate Histor... - $275.51
tensor - Intro to Kotlin (Basic Types, Type Infer... - $58.412
Congratulations, you've now learned how to filter an account's history using steem-python
, how to limit this to a certain time period, how to create an object using namedtuple
and format your output nicely!
Curriculum
Set up:
- Part 0: How To Install Steem-python, The Official Steem Library For Python
- Part 1: How To Configure The Steempy CLI Wallet And Upvote An Article With Steem-Python
Filtering
- Part 2: How To Stream And Filter The Blockchain Using Steem-Python
- Part 6: How To Automatically Reply To Mentions Using Steem-Python
Voting
- Part 3: Creating A Dynamic Autovoter That Runs 24/7
- Part 4: How To Follow A Voting Trail Using Steem-Python
- Part 8: How To Create Your Own Upvote Bot Using Steem-Python
Posting
- Part 5: Post An Article Directly To The Steem Blockchain And Automatically Buy Upvotes From Upvote Bots
- Part 7: How To Schedule Posts And Manually Upvote Posts For A Variable Voting Weight With Steem-Python
Constructing
Rewards
- Part 9: How To Calculate A Post's Total Rewards Using Steem-Python
- Part 12: How To Estimate Curation Rewards Using Steem-Python
- Part 14: How To Estimate All Rewards In Last N Days Using Steem-Python
Transfers
- Part 11: How To Build A List Of Transfers And Broadcast These In One Transaction With Steem-Python
- Part 13: Upvote Posts In Batches Based On Current Voting Power With Steem-Python
Account Analysis
The code for this tutorial can be found on GitHub!
This tutorial was written by @amosbastian in conjunction with @juliank.
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]
thanks for the tutorial, with this tutorial I can know how many votes that I get, hopefully this tutorial is not hard to do
Hey @steempytutorials 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
Hello out there!
Not sure if anyone will read this at all but if possible I'd love to get an answer...I'm trying to run this example:
![](https://steemitimages.com/640x0/https://steemitimages.com/DQmci4K254wwhSdRqkedhCKWxYf11XSRcEcUeFUcd4Uvt9m/image.png)
![](https://steemitimages.com/DQmVZzhWyJwyQ4eFnhJq4LWXv4nf26jrvanHZiBGyms8nU2/image.png)
But unfortunatelly, I get this error with both Python 2.7 and 3.6:
Is it a known issue or something wrong on my side?
I created a completely clean virtual environment, installed
steem-python
and tried running it and it worked fine for meYou can try upgrading your
steem-python
since maybe you have an older version. If that doesn't work you can also contact me on Discord at Amos#4622 and I can help you out!hmmm..thanks for ur work, I'll take a closer look on that and will let you know!
Which python version r u using?
Python 3.6.5 :: Anaconda custom (64-bit).