[Tutorial] Calculate who upvoted you the most (using SteemJS)steemCreated with Sketch.

in #steemdev7 years ago

Last time we learned how to calculate a user's reputation. Let's kick it up a notch this time and do something a little more complicated. We'll answer a question I bet many Steemians are curious to know!

"Who upvoted me the most?"



But first, let me tell you that soon you won't even have to calculate this yourself anymore. @sjennon and I are very busy working on a website where you can check all kinds of statistics like this very easily. We're going to launch our Beta version very soon but first we need a name for the app. You can help us by suggesting a great name, and you can even win $20 SBD doing so!

Anyway, in the meantime I'll explain how you can answer this question yourself by using the SteemJS library.

Fetching a user's posts

First we have to grab our posts so that we can look at all the upvotes.

To get our posts we use Steem.api.getDiscussionsByAuthorBeforeDate(). It expects four arguments:

  • username
  • startPermlink (optional) Permlink to a post before which we want to get our posts
  • beforeDate Date before which we want to get our posts*
  • limit Amount of posts (max 100)

* beforeDate seems to be broken, no matter what date we enter it returns the latest posts.

To keep it simple for now, we'll just grab the most recent 100 posts. Even if you posted a new blog every day it would still have data from the past 3 months, so that will do for now.

The second argument (startPermlink) can be null because we don't need to grab posts before any other post. This is something we will need if we want more than the last 100 posts, which we'll do in a later tutorial.

Because the beforeDate is broken we will just pass along January 1, 2100 so our app will be safe to use for the next 83 years. After that it's time to find a new hobby folks!

Get posts:

Steem.api.getDiscussionsByAuthorBeforeDate('pilcrow', null, '2100-01-01T00:00:00', 100)
    .then(posts => {
         // do something with posts here
    }); 

Getting all the upvoters on a post

Once we have the posts, it's time to look at who upvoted each. For this we use the property active_voteson each post.

Screen Shot 2017-08-11 at 11.56.16.png
A partial screenshot of a post's properties. active_votes allows us to see who voted on the post. And yes, I self-voted 😬

So let's see how we can make a list of all upvoters on post:

function getUpvoters(post) {
    return post.active_votes.map(upvote => upvote.voter);
}



For the post in the screenshot this will result in the following:

['pharesim', 'team', 'banjo', 'skririm', 'minnowsupport', 'pilcrow', 'itswetz', 'muxxybot', 'maestroq']

Adding upvoters for all posts together.

Now that we have a function to get all upvotes for one post, we can do this for all our posts. To combine them in one big array we use a reduce function. It starts with an empty array (all), and for every post we loop through it adds the upvoters on that post to it (all.concat(upvoters)).

function getAllUpvoters(posts) {
    return posts.reduce((all, currentPost) => {
        const upvoters = getUpvoters(currentPost)
        return all.concat(upvoters);
    }, []);
}

We can do this in a one-liner but I like to keep my code a bit readable

Now we have a much longer array with all upvoters on all our posts combined. If someone upvoted us twice, they will appear in this array twice. Which leaves us with the task of counting the occurrences.

Counting the amount of upvotes per user

To add up all vote counts per user, we use another reduce function. It starts with an empty object, and every time we loop over an upvoter we want to add its count to the object.

If we've counted the upvoter before it already has a count, otherwise we start at 1. Here's a quick one-liner to do that:

upvoteCounts[upvoter] = (upvoteCount[upvoter] || 0) + 1;

Meaning that if the upvoter is already in the object we grab that value, if he's not we start with 0. Then we add 1 to that number and write it back into the object. The complete function looks like this:

function countUpvoters(allUpvoters) {
    return allUpvoters.reduce((upvoteCounts, upvoter) => {
        upvoteCounts[upvoter] = (upvoteCounts[upvoter] || 0) + 1;
        return upvoteCounts;
    });
}

Putting it all together

Now that we have all the functions to calculate the amount of upvotes on our last 100 posts, let's put it together.

Steem.api.getDiscussionsByAuthorBeforeDate('pilcrow', null, '2100-01-01T00:00:00', 100)
    .then(posts => {
        const allUpvoters = getAllUpvoters(posts);
        return countUpvoters(allUpvoters);
    });

The result

And this is what the result will look like:

{
    "pharesim": 12,
    "team": 2,
    "banjo": 15,
    "skririm": 1,
    "minnowsupport": 15,
    "pilcrow": 26,
    "itswetz": 1,
    "muxxybot": 13,
    "maestroq": 1,
    "proctologic": 6,
    "nomadnessie": 1,
    "sjennon": 2,
    "personz": 1,
   ...
}

Demo on jsFiddle

I also made a jsFiddle example of this so you can play around with it. Enter your own username on line 4 (whoUpvotedMe('yourUserNameHere')) and see who upvoted you the most!

There's all kinds of other things you can do with this of course. You could keep the count in an array of follower objects instead so that you can sort them, for example. This is just a basic example of what you can do with information from the SteemJS API.

Was this useful to you? Do you have any suggestions or improvements? Let me know in the comments! ⬇

Sort:  

"There's an App for that" ... Actually, it's more of an external website, created by a Steemian.

Check out SteeMVP. It has a lot of cool information about who voted for you and how much (in dollars) the votes counted.

Great analysis and explanation though!

Thanks, someone already pointed that out to me but I didn't know that when I wrote this. I still think the app I'm building will be better than that so I'm going to continue anyway ;)

Yeah, the SteeMVP site leaves a lot to be desired .. it could be so much more useful than it currently sits. However, it is a very useful tool nonetheless.

I'm interested in seeing the final product of the app that you're building!

My app tells me that you don't follow me yet, but if you did you'd know when it's finished ;)

I have magical powers that help me find posts of people who I may not be following. Also known as a bookmark button :)

But I scrolled through your other posts and will follow you. Did your sweet app also tell you that I just passed 1k posts on Steemit!? :D

Haha, not yet but that feature will definitely be added. Congrats!

Thanks! I think it's slightly challenging to add a "milestone" feature, because you'll see some people on here who think that every 10 new followers is a milestone, even though they already have 1k+ followers.

Either way, milestones are fun, and every (active) follower DOES matter! :)

It's great that Steem has a public API. Thanks for jsFiddle link, it's always better to see the code in action and play with it.

Steemit needs a syntax highlighting for source code though ;)

Excellent!! It will be very useful for me in order to improve a tool that I'm developing.
https://joticajulian.github.io/steem-activity/index.html?account=pilcrow

Thank you for the tutorial, because when I enter to the repository of steem-js there is no much information about each function.

I think that an improvement of your tutorial is to see the weight of each upvote. The votes of whales are more important that votes of Minnows. Similar to this
http://steemreports.com/top-voters/@pilcrow

Great suggestion, thanks! I'm still figuring out how to calculate the exact SBD reward each upvote is worth, but the weight and percentage are readily available already.

I'll check out your tool as well, sounds interesting.

Thanks, very cool!

thanks Pilcrow. While I have 1000 + followers, I am clueless the metrics. Perhaps it will help me also be more discerning on who I follow too. Keep up the good work. Upvoted resteemed and followed.

Thanks for the feedback! As you may have read I'm working on an app that gives you a lot of insight in statistics like these. Keep an eye out for posts by me or @sjennon, we hope to launch a beta version of the app soon.

Hi, @pilcrow
It's a beautiful job. Congratulations on the content and the prize.
Deserved!
regards

Thank you!

Very helpful :)

very useful.