create account

[Hive Patched] 4 Steps - Advanced Vote Round With Friend List [MySQL & Steem-JS & Node-JS] by lonelywolf

View this thread on: hive.blogpeakd.comecency.com
· @lonelywolf ·
$30.58
[Hive Patched] 4 Steps - Advanced Vote Round With Friend List [MySQL & Steem-JS & Node-JS]
![hivejs.png](https://files.peakd.com/file/peakd-hive/lonelywolf/KcUde8ZP-hivejs.png)
(Want to use the logo yourself? no problem, check out the post I made about [My Art Design For Hive Logo](https://hive.blog/hive-174578/@lonelywolf/art-design-hive-logo-by-lonelywolf-stav-art-inside-free-usage))
(Want to use the thumbnail above? you can use it for free, don't forget to leave a credit 😀)
## Full project installation at the ***END*** of the tutorial
---
#### Repository: 
https://www.npmjs.com/package/steem-js-patched

# All of this tutorial is patched for Hive, so it works for Hive and steem!
#### All of the examples and results is from the old tutorial but still same for hive!


- ## Helpful tutorials:
[[HIVE Patched] SteemJS Full Tutorial - All The Functions - All The Abilities](https://hive.blog/hive-139531/@lonelywolf/hive-patched-steemjs-full-tutorial-all-the-functions-all-the-abilities)
[[Hive Patched Tutorial] SteemJS - Vote, Comment and Follow functions - All In One](https://hive.blog/hive-139531/@lonelywolf/hive-patched-tutorial-steemjs-vote-comment-and-follow-functions-all-in-one)

---

### Step 1 - Setup The HTML File

I'm using bootstrap, you can use it if you want.

first, make a new HTML-5 document

```
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
 
</body>
</html>
```

at the head add your stylesheet files (not important) and add the steemjs and your js files.

```
<head>
  <meta charset="UTF-8">
  <title>Vote, Resteem and comment</title>
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    <link rel="stylesheet" href="style.css" type="text/css" />
    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.2.0/css/all.css" integrity="sha384-hWVjflwFxL6sNzntih27bfxkr27PmbbK/iSvJ+a4+0owXq79v+lsFkW54bOGbiDQ" crossorigin="anonymous">
</head>
```

`title` - the HTML page title

`meta` - these 2 rows make the page work at any type of view, phone, tablet, pc, etc.

`stylesheet` - the first row is bootstrap, bootstrap is a CSS framework to make your styling easier.
the second row is our CSS file, with this file we going to fix some issues with the bootstrap styling and add our styling.
the third row is the `font-awesome` stylesheet file, this is font as text, for example, you want a smiley face but not an image, you can use `font-awesome` to do it as a plain text.

at the end of the body add the javascript scripts

```
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.steemjs.com/lib/latest/steem.min.js"></script>
            <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.1.1/socket.io.js"></script>

    <script src="js.js"></script>
```


we're adding `Jquery`, `SteemJS`, `Socket.IO` and our js file.
#### Step 1.1 - Add Friend Form

we need to make a form to add friends into our SQL database.

```
    <div class="add-friend">
      <input type="text" class="form-control" id="friend-name" placeholder="steemit username (without @)" />
      <button id="add-friend" class="btn btn-primary"><i class="fa fa-plus"></i> Add</button>
    </div>
    <br>
```

we need only input text and button, at the CSS side we going to work on `step 2`.

so at the input text, we need the id `friend-name` to know that this is the friend name input,
at the button, we need the id `add-friend` so we can know which button the user pressed.

result - 

![](https://i.imgur.com/ssM4IWr.png)

#### Step 1.2 - Settings Form

so we've done with the first form, now we need a settings form, at this form we need

- account username (the voter username)
- account private posting wif key (the voter wif key)
- round time

so we need 2 input texts, restart round button and save button.

```
    <div class="settings">
      <div class="text-input" style="border-bottom-left-radius:0; border-bottom-right-radius:0;">
        <i class="fa fa-user"></i>
        <input type="text" id="acc_name" placeholder="Username..." class="form-control" />
      </div>
      <div class="text-input" style="border-top-left-radius:0; border-top-right-radius: 0;">
        <i class="fa fa-lock"></i>
        <input type="password" id="acc_wif" placeholder="WIF Key..." class="form-control" />
      </div><br>
      <button class="btn btn-primary" id="restart-round"><i class="fa fa-sync-alt"></i> Restart Round</button>
      <button class="btn btn-success" id="save-settings"><i class="fa fa-cog"></i> Save Settings</button><br>
      <span class="label" id="settings-update">Settings Updated Succesfully</span>
    </div>
    <br>
```

again, the CSS step is only at `step 2`, so first, we have the username input text,
second the wif key input text,
then the restart round button and the save settings button.

At the end we have a `span` with the class label, we going to use it when we restart a round or saving the settings, default it will not be displayed on the page.

result - 

![](https://i.imgur.com/H52aiAf.png)

#### Step 1.3 - Round Timer & Friends List Table

- first, we're going to make the round timer.

```
    <div class="next-round">
      <span class="next_round">Next Round</span>
      <span id="round-timer">00:00:00</span>
    </div>
    <br>
```

so the `div` class is next-round, inside we have a span with the class `next_round` and another span with the id `round-timer`
the round timer is "00:00:00" default but when we go into `step 3` we're going to add js to this and it will countdown the time.

result (after js) - 
![](https://i.imgur.com/hlQUUR5.png)

- now we're going to work on the friends list table

```
    <table class="table">
      <thead>
        <tr>
          <th scope="col">#</th>
          <th scope="col">Username</th>
          <th scope="col">Options</th>
        </tr>
      </thead>
      <tbody>
      </tbody>
    </table>
```

here we're making a simple table  with `#`-ID, `Username`-The Steemit Username,`Options`-Options Buttons(`Delete`)

### Step 2.0 - Javascript, countdown the next round, Steem API
before everything, we want to use the **HIVE** api so we broadcast on the hive blockchain and not on steem blockchain!

```
steem.api.setOptions({ url: 'https://api.hive.blog' });
```
first, we'll make the actual countdown function

```
    // Update the count down every 1 second
    var x = setInterval(function() {

      // Get todays date and time
      var now = new Date().getTime();

      // Find the distance between now and the count down date
      var distance = countDownDate - now;

      var hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
      var minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60));
      var seconds = Math.floor((distance % (1000 * 60)) / 1000);


      document.getElementById("round-timer").innerHTML = hours + ":"
        + minutes + ":" + seconds;

      if (distance < 0) {
        clearInterval(x);
        document.getElementById("round-timer").innerHTML = "EXPIRED";
        var newDate = addMinutes(120);
        socket.emit("vote_round", newDate);
      }
    }, 1000);
```

first, we get the current time, then the distance the time we want to get (example 12:00) and now the time is 10:00, so the distance is 2 hours at date time JS.

then we calculating the hours, minutes and seconds.

then we change the HTML (the text) on `round-timer` span ID with hours:minutes: seconds, example: 2:30:15

then we check if the distance is 0 or less we make a restart for the round with socketIO

at the top of the script paste this `var countDownDate = addMinutes(120);` it will make the `countDownDate` variable for 2 hours from now (example: now the time is 10:30, so the variable will equal to 12:30)

addMinutes Function -

```
function addMinutes(minutes) {
    return new Date().getTime() + minutes*60000;
}
```
simple enough, we take the minutes and add them to the current time.
60,000 milliseconds = minute.

#### Step 2.1 - sockets and functions

at this step we're going to make the sockets, I mean, we're going to take actions from the server and send actions to the server, at first we'll start with the actions we get from the server and the actions we send and at step 4 we're going to do that at the server-side.

at first, we're going to get the date that saved at the database.

```
    socket.on("get_date_sql", function(date){
      if(new Date().getTime() > date){
        var newDate = addMinutes(120);
        socket.emit("vote_round", newDate);
      }else
        countDownDate = date;
    });
```

at the server side when the socket starts we're going to send the date time from the database to the js file and we're loading it to the round timer.
we're checking if the database date is less then the current time, example: DB time = 12:00 and the current time is 14:00
if it's true we're going to make a restart to the round and start a voting round (send the action to the server)
if it's false the variable `countDownDate` we'll be equal to the DB date.

- restart round

```
    $("#restart-round").click(function(){
      const dateNow = addMinutes(120);
      socket.emit("update_round", dateNow);
    });
```

very simple, we're sending the action to the server with the new date time, at the server side we're going to update it at the database.

- save settings

```
    $("#save-settings").click(function(){
      $acc_name = $("#acc_name").val();
      $acc_wif = $("#acc_wif").val();
      socket.emit("update_settings", {name: $acc_name, wif: $acc_wif});
    });
```
again, pretty simple, we're getting the account name and wif key and send it to the server and at the server side updating it on the database.

- add friend

```
    $("#add-friend").click(function(){
      $name = $("#friend-name").val();
      socket.emit("add_friend", $name);
    });
```

we're getting the name from the input text and sending an action to the server, at the server side we're updating the database.

- update timer

```
    socket.on("update_timer", function(date){
      countDownDate = date;
      $("#settings-update").html("Round Restarted Succesfully!");
      $("#settings-update").css("color", "#3bc13b");
      $("#settings-update").slideToggle(300);
      setTimeout(function(){$("#settings-update").slideToggle(300);}, 3000);
    });
```

at this time we're getting action from the server, the variable `countDownDate` will be equal to the date from the server,
then we're updating the settings update label and fade it out after 300ms.

- add a friend to list

```
    socket.on("add_friend_to_list", function(data){
      var html = '<tr id="row-'+data.id+'"><th scope="row">'+data.id+'</th> <th>@'+data.name+'</th><th><button id="delete" onclick="deleteUser('+data.id+')" class="delete"><i class="fa fa-times"></i></button></th></tr>';
      $(".table > tbody").append(html);
    });
```

again we're getting action from the server, here it's really easy.
we're making a variable with the HTML data, check it out to get a better look on it.

then we append the variable to the table.

- delete user

```
    socket.on("deleteuser", function(id){
      $("#row-"+id).remove();
    });
        
        function deleteUser(id){
     socket.emit("deleteuser", id);
   }
```
agagin action from the server, at this time we're just deleting a row from the table, this is the reason for the `row-id` at the `add friend to list` function.

we're using the function at the delete button on the table, if you didn't saw check out the html 
`<tr id="row-'+data.id+'"><th scope="row">'+data.id+'</th> <th>@'+data.name+'</th><th><button id="delete" onclick="deleteUser('+data.id+')" class="delete"><i class="fa fa-times"></i></button></th></tr>`

- settings updated / failed

```
    socket.on("settings_updated", function(){
      $("#settings-update").html("Settings Updated Succesfully!");
      $("#settings-update").css("color", "#3bc13b");
      $("#settings-update").slideToggle(300);
      setTimeout(function(){$("#settings-update").slideToggle(300);}, 3000);
    });
        
        socket.on("settings_failed", function(){
      $("#settings-update").html("Settings Update Failed!");
      $("#settings-update").css("color", "#ff2e2b");
      $("#settings-update").slideToggle(300);
      setTimeout(function(){$("#settings-update").slideToggle(300);}, 3000);
    });

```

just a simple text with fading in and out.


### Step 3 - Setup The Database


`note`: **I'm using XAMPP for the mysql service (and PHPMyAdmin).**

first, go to your phpmyadmin `localhost/phpmyadmin` this is the default URL.
create a new database with the name `friend_list`

![](https://i.imgur.com/xqPtlOZ.png)

and create 2 tables, first - settings

at settings, you need `acc_name, acc_Wif and date`

![](https://imgur.com/o0fItus.png)

the second table is `friends`

you need only `id` and `username`, the id will be A_I it means that it will be filled automatically

![](https://i.imgur.com/0jhKS9A.png)

and for this part, we have done.

### Step 4.1 - Server Side (Setting Up The Server)

first, we're going to set up the server

install the packages we're going to use:
`npm install steem-js-patched socket.io path express mysql --save`
```
const steem = require('steem-js-patched'),
    fs = require('fs'),
    path = require('path'),
    express = require('express'),
    socket = require('socket.io'),
    mysql = require('mysql'),
    port = 8000;

steem.api.setOptions({ url: 'https://api.hive.blog' }); // Setting up the API to HIVE api
```

you need all those packages to be installed on your node(npm) system and the API of the hive to broadcast to the **hive** blockchain.

```
//App setup
var app = express();
var server = app.listen(port, function () {
    console.log("listening to port " + port);
    console.log("script is running...");
});
var io = socket(server);
```

here we're making the `app` variable, this is the basic server using express, then we're listening to the port (port=8000) so we can connect to the server from the web browser.
then we're making a connection with the socket.io with the server variable.

#### Step 4.2 - Database Connection

first, we're going to make an array with the database name, password, username, and host.
```
//MySQL setup
const config = {
  "host": "localhost",
  "user": "root",
  "password": "",
  "base": "friend_list"
};
```

now we just need to make the connection with the information.

```
var db = mysql.createConnection({
  host: config.host,
  user: config.user,
  password: config.password,
  database: config.base
});

db.connect(function (error) {
  if (!!error)
  throw error;

  console.log('mysql connected to ' + config.host + ", user " + config.user + ", database " + config.base);
});
```

at first, we're making a variable called `db` we're going to using it on the script a lot, this function making the connection with the mysql database.

then we're connecting the database with the script (`db.connect`)

#### Step 4.3 - Functions

- vote function

```
//Vote Post Function
function streamVote(ACC_NAME, ACC_KEY, author, permalink, weight) {
  weight = weight * 1000;
    steem.broadcast.vote(ACC_KEY, ACC_NAME, author, permalink, weight, function(err, result) {
        if(err) return console.log(err);
        else
          return console.log('Voted Succesfully, permalink: ' + permalink + ', author: ' + author + ', weight: ' + weight / 100 + '%.');
    });
}
```

same as the latest tutorials, we get the user, wif, author, permlink and weight and broadcast it through the broadcast. vote function from steemjs

#### Step 4.4 - server side sockets
first, we need to make a connection with the socket.io from the client to the server.

```
io.on('connection', function (socket) {
    console.log("socket connected!");
        });
```

simple enough we check when the connection started and sending a comment to the console.

- load friend list + load date time 

```
    socket.on("load_list", function(){
      db.query("SELECT * FROM `friends`", function(error, result){
        if(!!error)
          throw error;
        result.forEach(function(res){
            socket.emit("add_friend_to_list", {id: res.id, name:res.Username});
        });
      db.query("SELECT * FROM `settings`", function(err, res){
        if(!!err)
          throw err;

        if(res[0].date)
          socket.emit("get_date_sql", res[0].date);
      });
      });
```

easy enough, we're making a query that loads the list of the users from the database and then adding them to the table on the client-side.
then we're getting the date-time from the settings database and send it to the client-side.

- add a friend to the database

```
    socket.on("add_friend", function(name){
      db.query("INSERT INTO `friends`(`Username`) VALUES(?)", [name], function(err, res){
        if(!!err)
          throw err;
        console.log(res);
        db.query("SELECT * FROM `friends` WHERE `Username`=?", [name], function(error, result){
          if(!!error)
            throw error;
          socket.emit("add_friend_to_list", {id: result[0].id, name:result[0].Username});
        });
      });
    });
```

simple enough we're making an insert to the friends table on our database with the username that we get from the client-side and update it on the database and on the client-side table.

- delete a friend from the database

```
    socket.on("deleteuser", function(id){
      db.query("DELETE FROM `friends` WHERE `id`=?", [id], function(err, res){
        if(!!err)
          throw err;
        console.log(res);
        socket.emit("deleteuser", id);
      });
    });
```

again really simple we're just deleting the row from the table and then we're deleting the row from the table at the client-side.

- update round (restart round)

```
    socket.on("update_round", function(dateNow){
      db.query("UPDATE `settings` SET `date`=?", [dateNow], function(err, res){
        if(!!err)
          throw err;

        console.log(res, dateNow);
        socket.emit("update_timer", dateNow);
      });
    });
```

really simple, we're updating the `date` at the setting table and restarting the timer on the client side to the new date.

- vote round 

```
    socket.on("vote_round", function(date){
      db.query("UPDATE `settings` SET `date`=?", [date], function(err, res){
        if(!!err)
          throw err;

        console.log(res, date);
        socket.emit("update_timer", date);
      });

      db.query("SELECT * FROM `friends`", function(err, result){
        if(!!err)
          throw err;

        console.log("vote round start, vote cast each 20 seconds!");
        var time = 1;
        db.query("SELECT * FROM `settings`", function(err, ress){
          result.forEach(function(res){

            setTimeout(function(){
                if(!!err)
                  throw err;
                steem.api.getDiscussionsByBlog({tag: res.Username, limit: 1}, function(err, result){
                  streamVote(ress[0].acc_name, ress[0].acc_wif, result[0].author, result[0].permlink, 2);
                });
            }, (time+=20)*1000);

          });
        });
      });
    });
```

first, we're making an update to the date (timer) as we did at the update round socket.

then we're getting the friend list from the database and making a loop that goes on every user, we're making a 20 seconds vote per user so all the votes will be cast successfully because there is a limit for 1 vote per 20 seconds with steemjs.

- update settings

```
    socket.on("update_settings", function(data){
      db.query("SELECT * FROM settings", function(err, res){
        if(!!err)
          throw err;

        if(!res[0]){
          db.query("INSERT INTO `settings`(`acc_name`, `acc_wif`) VALUES(?, ?)", [data.name, data.wif], function(errr, ress){
            if(!!err)
              throw err;

            console.log(ress);
            socket.emit("settings_updated");
          });
        }else{
          db.query("UPDATE `settings` SET `acc_name`=?, `acc_wif`=?", [data.name, data.wif], function(errr, ress){
            if(!!errr)
              throw errr;

            console.log(ress);
            socket.emit("settings_updated");
          });
        }
      });
    });
```

first, we're getting the settings and check if there are any settings inside if there is we're going to make an update to the table if there's nothing inside the table we're going to insert the details to the table.

**And here we're done**

we did all of that to get this result

![](https://i.imgur.com/L2vZx3S.png)
![](https://i.imgur.com/hsidGZO.png)

Hope I helped you if you have any suggestions for the next tutorials leave a comment and upvote!

thanks a lot, have a good day!

### Download The Files

you can download the files from google drive [Here](https://drive.google.com/open?id=1gV-ZFkF5mQiknh2wP3ukLBaroSXVthmm)
You will need to setup the **Hive** api to make it work on hive
```
steem.api.setOptions({ url: 'https://api.hive.blog' });
```
with that code line in client & server side

# Have a good day!
👍  , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ,
properties (23)
authorlonelywolf
permlinkhive-patched-4-steps-advanced-vote-round-with-friend-list-mysql-and-steem-js-and-node-js
categoryhive-139531
json_metadata{"app":"peakd/2020.03.14","format":"markdown","tags":["tutorial","javascript","hivejs","steemjs","mysql","nodejs","advanced","advanced-tutorial"],"users":["lonelywolf"],"links":["/hive-174578/@lonelywolf/art-design-hive-logo-by-lonelywolf-stav-art-inside-free-usage","https://www.npmjs.com/package/steem-js-patched","/hive-139531/@lonelywolf/hive-patched-steemjs-full-tutorial-all-the-functions-all-the-abilities","/hive-139531/@lonelywolf/hive-patched-tutorial-steemjs-vote-comment-and-follow-functions-all-in-one","https://drive.google.com/open?id=1gV-ZFkF5mQiknh2wP3ukLBaroSXVthmm"],"image":["https://files.peakd.com/file/peakd-hive/lonelywolf/KcUde8ZP-hivejs.png","https://i.imgur.com/ssM4IWr.png","https://i.imgur.com/H52aiAf.png","https://i.imgur.com/hlQUUR5.png","https://i.imgur.com/xqPtlOZ.png","https://imgur.com/o0fItus.png","https://i.imgur.com/0jhKS9A.png","https://i.imgur.com/L2vZx3S.png","https://i.imgur.com/hsidGZO.png"]}
created2020-04-15 15:30:00
last_update2020-04-15 15:30:00
depth0
children2
last_payout2020-04-22 15:30:00
cashout_time1969-12-31 23:59:59
total_payout_value15.290 HBD
curator_payout_value15.286 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length21,397
author_reputation25,295,791,457,391
root_title"[Hive Patched] 4 Steps - Advanced Vote Round With Friend List [MySQL & Steem-JS & Node-JS]"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id96,852,602
net_rshares83,633,627,006,275
author_curate_reward""
vote details (54)
@codingdefined ·
I can see "@utopian-io" :p.
Nice explanation :)
properties (22)
authorcodingdefined
permlinkq8ucs5
categoryhive-139531
json_metadata{"users":["utopian-io"],"app":"hiveblog/0.1"}
created2020-04-15 18:02:30
last_update2020-04-15 18:02:30
depth1
children1
last_payout2020-04-22 18:02:30
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length47
author_reputation529,012,741,958,951
root_title"[Hive Patched] 4 Steps - Advanced Vote Round With Friend List [MySQL & Steem-JS & Node-JS]"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id96,854,211
net_rshares0
@lonelywolf ·
Hhh yea as I mentioned, this is a remake for the old tutorial for steem that I made for utopian 

Everything is patched to work with hive so it's okay😃
properties (22)
authorlonelywolf
permlinkq8udfd
categoryhive-139531
json_metadata{"app":"hiveblog/0.1"}
created2020-04-15 18:16:24
last_update2020-04-15 18:16:24
depth2
children0
last_payout2020-04-22 18:16:24
cashout_time1969-12-31 23:59:59
total_payout_value0.000 HBD
curator_payout_value0.000 HBD
pending_payout_value0.000 HBD
promoted0.000 HBD
body_length151
author_reputation25,295,791,457,391
root_title"[Hive Patched] 4 Steps - Advanced Vote Round With Friend List [MySQL & Steem-JS & Node-JS]"
beneficiaries[]
max_accepted_payout1,000,000.000 HBD
percent_hbd10,000
post_id96,854,369
net_rshares0