Fetching a users posts from a hive api node (Client Side Methods)

in Programming & Dev3 years ago

dottrack.png

Project .Track is unrelated

That's just what I happened to have loaded in VS Code while working on the body of this post, which is fetching all a users posts into local storage... as shown on the right side of the image. .Track is something I'll be announcing more on later as a @blokz app assistant for those that use https://self-help.dev/ (Site is not ready in its current state, but you can feel free to check out the "under construction" side of it all)...

Back to the users posts

Now, this is most likely not the best way to be doing this... in fact, I know it isn't (and I'll cover what's next for this script at the end of this article), but currently this is what I've been using to fetch all a users hive posts into local storage in my browser. This will eventually make it's way into https://personal.community as a cached posts feature... So I'll have all the data available in browser to do all kinds of fun things with, like auto populate favorite tags and search users posts, etc...
Anyways, onto the main part of this...

Why not use Condenser

Because I don't believe fatty servers running fatty services is the future, I believe client side static content is the future of $hive apps and services, now, I do realize that not everything logistically functions without a server running with some private keys saved doin things, but from a decentralized and security standpoint, it makes more sense to skip the middleman for the data, and get it directly from the full nodes, instead of have me goto a page, have their (peakd, hive.blog, etc) servers ping their full node, then send me the data. Hopefully others see the benefits in skipping the middlemen (nothing against em, I love @peakd). Anyways, getting a bit off topic.. back on track..

So I'll say it again, I really have no idea what I'm doing when I'm programming... I thought i had a good grip on it... but there is a lot I don't know, like async and promises and arrow functions, but that will all come with time.. So as I fumble my way around the world and figure things out,... I write bad code, like this, which works, in the sense that I get 100 posts per page refresh...

Complete solution

window.onload = function () {

  let apinode = "https://api.deathwing.me";
  let hiveaccount = "sn0n"
  let startpermlink = ""
  let beforedate = ""
  let xhr = new XMLHttpRequest();
  let response = ""
  let data = '{"jsonrpc":"2.0", "method":"tags_api.get_discussions_by_author_before_date", "params":{"author": "' + hiveaccount + '","start_permlink":"' + startpermlink + '","before_date":"' + beforedate + '","limit":100}, "id":1}';

  xhr.open("POST", apinode);
  xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
  xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {
      console.log(xhr.status);
      console.log(xhr.responseText);
      response = JSON.parse(xhr.responseText);
      for (i = 0; i < 100; i++) {
        if (response.result[i] !== undefined) {
          console.log('lets try this post:' + JSON.stringify(response.result[i]));
          localStorage.setItem("index", JSON.stringify(response.result[i].author) + "." + JSON.stringify(response.result[i].permlink) + "." + JSON.stringify(response.result[i].created));
          localStorage.setItem(JSON.stringify(response.result[i].author) + "." + JSON.stringify(response.result[i].permlink), JSON.stringify(response.result[i]));
        } else {
          console.log(response.result)
          localStorage.setItem("index", "done")
        }
      }
    }
  };

  if (localStorage.getItem("index") === "done") {
    console.log("all posts cached")
  } else if (localStorage.getItem("index") !== null) {
    console.log(localStorage.getItem("index"));
    let fetchNew = localStorage.getItem("index").split('.');
    console.log(fetchNew[0].replace(/"/g, ""));
    hiveaccount = fetchNew[0].replace(/"/g, "")
    console.log(fetchNew[1].replace(/"/g, ""));
    startpermlink = fetchNew[1].replace(/"/g, "")
    console.log(fetchNew[2].replace(/"/g, ""));
    beforedate = fetchNew[2].replace(/"/g, "")
    data = '{"jsonrpc":"2.0", "method":"tags_api.get_discussions_by_author_before_date", "params":{"author": "' + hiveaccount + '","start_permlink":"' + startpermlink + '","before_date":"' + beforedate + '","limit":100}, "id":1}';
    xhr.send(data);
  } else {
    xhr.send(data);
  }

};

The Breakdown

Lets start to break it down... and propose solutions to fix it up..

  let apinode = "https://api.deathwing.me";
  let hiveaccount = "sn0n"
  let startpermlink = ""
  let beforedate = ""
  let xhr = new XMLHttpRequest();
  let response = ""
  let data = '{"jsonrpc":"2.0", "method":"tags_api.get_discussions_by_author_before_date", "params":{"author": "' + hiveaccount + '","start_permlink":"' + startpermlink + '","before_date":"' + beforedate + '","limit":100}, "id":1}';

apinode can be any full api node you like, I know @deathwing has one of the best full nodes, so i let him be the witness to capture all my requests...
hive account is whatever user you may wish to retrieve posts of.
hiveaccount is the account we are working with, startpermlink and beforedata are used once we have some idea of the last post we retrieved and saved to localstorage with localStorage.setItem("index", JSON.stringify(response.result[i].author) + "." + JSON.stringify(response.result[i].permlink) + "." + JSON.stringify(response.result[i].created)); which is the author, permlink and when the last post of the previous request was made. XMLHttpRequest() is what JavaScript uses to do AJAX type things, that's request data from an external website. and data is our initial request for a users posts.

Following that bit of code is some xmlhttprequest bits and

       if (response.result[i] !== undefined) {
          console.log('lets try this post:' + JSON.stringify(response.result[i]));
          localStorage.setItem("index", JSON.stringify(response.result[i].author) + "." + JSON.stringify(response.result[i].permlink) + "." + JSON.stringify(response.result[i].created));
          localStorage.setItem(JSON.stringify(response.result[i].author) + "." + JSON.stringify(response.result[i].permlink), JSON.stringify(response.result[i]));
        } else {
          console.log(response.result)
          localStorage.setItem("index", "done")

This if else basically says 'if we got a response that isn't undefined', lets save some info to the localstorage, first is our 'index' which we use to start bootstrap our next request, followed by a nice long localStorage.setItem(JSON.stringify(response... which saves the author and permlink (what is needed for a URL) and then the actual post data (.result[i]) i being the current post from the string of 100 we requested. We also have an else statement if i is undefined, which I should swap to check if it's larger then 1 byte or something, but essentially says if there isn't a response, lets just say we are 'done' in index.

the last bit of code, a very long if (localStorage.getItem("index") === "done") { which is basically starting the block of 'is this our first request or a follow up visit?', if index is saved in the localstorage and set to "done", we will just do nothing and say all old posts are cached, Currently this does NOT fetch new posts since this all ran... a new loop needs to be added to look for posts since we started this process, another bit on my todo list of 'features' for this to be complete... but for our purposes, we just want to get an authors previous posts and use that data today, we don't necessarily NEED to be forward thinking with the data... in any event... following a check for 'done' in our index we have a check to see if index isn't 'null', and if something other then done is in index we go ahead and start updating our data variable with the info found inside our index. lastly is the final else, which says, "ok, so we aren't done with index, we haven't even initiated index with useable data, so index doesn't exist, lets send out our first request for a users posts" basically.. with xhr.send and the info from our initially loading data variable in the first part.

What's Next

fetch("https://api.hive.blog", {
  body: `{"jsonrpc":"2.0", "method":"bridge.get_account_posts", "params":{"sort":"posts","account": "sn0n",  "limit": 20}, "id":1}`,
  headers: {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  method: "POST"
})
.then(response => response.json())
.then(data => console.log(data));

// adding 
// "start_permlink": "stoned-stream-of-consciousness-goal-planning","start_author": "sn0n",

fetch("https://api.hive.blog", {
  body: `{"jsonrpc":"2.0", "method":"bridge.get_account_posts", "params":{"sort":"posts","account": "sn0n","start_permlink": "stoned-stream-of-consciousness-goal-planning","start_author": "sn0n",  "limit": 20}, "id":1}`,
  headers: {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  method: "POST"
})
.then(response => response.json())
.then(data => console.log(data));

This bit is the new request format I'll be using testing next, swapping from XMLHttpRequest() to fetch(). The first part is requesting the most recent posts, the second fetch is using start_permlink as well as start_author similar to how tags_api.get_discussions_by_author_before_date does its requests, but @rishi556 let me know that bridge.get_account_posts was the more future proof request, so that shall be where I go, although they do request similar data, i do know that #hivemind is going thru a lot of growth and not all legacy requests will be around forever, so wanted to make sure this is some work that will age well with time.

breaking news!

This just in, as I was editing this post before heading off to implement the new fetch stuff, @rishi556 let me know about json-rpc which i have no idea if its what I'm looking for, but I'll be heading down that rabbit hole after submitting this post...

Soo Much Extra Signature


If you like this post, please support me with a trifecta!!!

Follow, Upvote & ReBlog!

Please leave a comment below.

Donations

blokz.io is a self-help and personal development driven project with some lofty goals, help is always welcome! With that said, these funds will be used for work on blokz.io & other costs of the project

BTC: bc1q5z9vqa8eyrlc0we3aa5kmr9mgkfhzknxqj4zh8

LTC: MPm8njHYpyDZFcT72EA4VrUFwRjuwueUUV

ETH: 0xb3106cEF1dcBbBABB4949b012A7009C290817F74

DOGE: DMnBtX24mXFGWDDPywqSV2BmtRaLv9pV1c

CashApp: $blokzio

GitHub :
https://github.com/blokz

Let's chat:
https://discord.gg/CgE3Sgr

@sn0n

‎snahn ip

https://blokz.io/

‎#DriveIdeas2Creation

TLDR;

Wrap-Up & A call to action

Well, off to implement this new function, have a beautiful day, and let me know what you think with a up or down vote and definitely leave some feedback on what you would do (or have done) to fetch all a users posts client side.

Sort:  

Both condenser and peakd make client side calls to get their data. Hive.blog does have server side rendering for SEO reasons, but regular condenser doesn't. What you are looking for is possible with them.