Discovery-it Curation Bot just born and how it works [ENG/ITA]

Words
1684
Reading
8 min
Listen
Play
7y

[ENG]

Introduction

I am happy to inform the Discovery-it community that a bot for post curation has been running for about a week now.
Its operation is very simple and is available to the Discovery-it curators.
To do this I was inspired by beerlover@beerlover's !BEER command and tipu@tipu's tipu@tipu curate command.
In fact, when a curator wants to vote on a post with the discovery-it trail, he simply has to comment under the post with the command !Discovery 30, where 30 indicates the percentage of the vote. Obviously the percentage can also be different, for now values ​​between 30% and 50% are allowed.
In addition, you can also insert this command within a comment, so that you can create more complex and nice comments. For example I could write: "Congratulations a !Discovery 50 is what you deserve" or anything else.

How does it work

  • First of all, the use of this bot is reserved for the curators of discovery-it therefore inside it there is a list with the username of the curators.

  • Every 30 seconds the bot reads the last comment made by the curators and checks two things:
    1) if the !Discovery 30 command is contained in the comment and that the command is well structured.
    The correct syntax is !Discovery+space+number
    The number must be between 30 and 50 and must be an integer
    2) if the discovery-it@discovery-it account has already voted on the post under which the command appears.

  • In case the command is found and the discovery-it@discovery-it account did not vote on the post, the bot votes on the post and comments with the classic discovery's comment. Otherwise it does nothing and waits 30 seconds for a new check.

Code

The script is written in the Python language and uses the official hive library, adapted for hive by pharesim@pharesim. If you are interested you can find it here.
Now I will show you step by step how the code is structured and I would be grateful if someone more experienced than me can give me some advice on how to improve the script.

1) Let's import the modules necessary for operation

import string
import random
import time
from hive import Hive
from hive.hived import Hived
from hive.post import Post
from hive.account import Account
from hivebase.exceptions import RPCError 

2) Let's initialize the list of Hive's curators and nodes

curators = ['curator1','curator2','curator3']
hived_nodes = ['https://api.hive.blog','https://anyx.io','http://anyx.io','https://api.hivekings.com']

Of course instead of curator1-2-3 put the names of your curators, also you can always add other curators and other nodes. Just edit these lines of code and then save the file.
For an updated and functioning list of nodes you can consult the posts of fullnodeupdate@fullnodeupdate

3) Let's create the Hive object with the list of nodes and the private posting key of the account that will vote, in this case discovery-it@discovery-it

s = Hive(nodes = hived_nodes,keys = ['private posting key'])

Clearly instead of 'private posting key' replace the real private posting key.

4) Let's define some functions necessary for operation

def extract_identifier(url):
    ini = url.find('@') + 1
    fin = url.find('#')
    return url[ini:fin]

def extract_percentage(comm,command):
    ini = comm.find(command)
    comm = comm[ini:]
    num = ''
    for i in range(len(command),len(comm)):
        if comm[i].isdigit() == True:
            num = num + comm[i]
    if comm.find(num) == -1: return ''  
    return num

def check_perc(perc):
    if perc == '': return False
    elif int(perc) > 50 or int(perc) <= 29: return False
    else: return True

The extract_identifier function extracts the post identifier from the post url, ie the string "author/permlink"

The extract_percentage function is the one that deals with the extraction of the vote percentage chosen by the curator.
Discard any non integer numbers by returning an empty string. Return an empty string even if no number is present. Otherwise it returns the percentage number.

The check_perc function instead checks if the voting percentage is between 30% and 50%

So these last two functions verify that the command is well structured.

5) Let's create a list of queries to pass to the * get_discussion_by_comments * function to extract information from the blockchain on the last comment made by the curators.
query_list = []
for curator in curators:
    query_list.append({"limit":1,"start_author":curator})

Here "limit": 1 tells the blockchain how many comments we want, in this case only 1, the last one. If instead of 1 we put 3 we will see the last 3 comments made by a particular user.

Well now let's see the central core of the program, all contained in a "try except" block in order to handle any exceptions usually caused by connection problems to the nodes.

6) The main part

while True:
    try :
        dict_list,comment_list,url_list,identifier_list = [],[],[],[]
        for i in range(len(curators)):
            dict_list.append(s.hived.get_discussions_by_comments(query_list[i])[0]) 
            comment_list.append(dict_list[i]['body'])
            url_list.append(dict_list[i]['url'])    
            identifier_list.append(extract_identifier(url_list[i]))     

For each curators, it queries the blockchain using the get_discussion_by_comments function and from the last comment made it extracts 3 lists: one for comments, one for urls of posts, and another for identifiers.

        a = Account('discovery-it')
        index = -1
        command_found = ''
        command = '!discovery '
        for i in range(len(comment_list)):
            if comment_list[i].find(command) != -1 and a.has_voted(Post(identifier_list[i])) == False:
                index = i   
                command_found = comment_list[i]
                break

It creates the Account object for our voting account and define the command to search for, that is !Discovery . Then check if the command is present in the comments list and if our account hasn't voted on the post. If the result is positive, it records the comment in question and its index in the list in two variables.

        if index != -1:
            perc = extract_percentage(command_found,command)
            if check_perc(perc) == True:
                perc = float(perc)
                s.commit.vote(identifier_list[index],perc,'discovery-it')
                body = '
https://cdn.steemitimages.com/DQmTAn3c753LR7bHCLPo96g9UvRMaPFwaMYn8VQZa85xczC/discovery_logo_colore%20-%20Copia.png

\n\nQuesto post è stato condiviso e votato all\'interno del discord del team curatori di discovery-it Entra nella nostra community! [hive-193212](https://hive.blog/trending/hive-193212)\nThis post was shared and voted inside the discord by the curators team of discovery-it. Join our community! [hive-193212](https://hive.blog/trending/hive-193212)
'
permlink = ''.join(random.choices(string.digits+string.ascii_lowercase,k=10)) s.commit.post(title='',body=body,author='discovery-it',permlink=permlink,reply_identifier=identifier_list[index]) print(curators[index]+' has curated '+identifier_list[index]+' with '+str(perc)+'%') time.sleep(30) except RPCError: print('Problem of connection to the nodes, I wait 30 seconds and restart') time.sleep(30)

Now if the command has been found, the code checks that this is well structured and if so, votes and comments on the post creating a random permlink of 10 characters. He also writes in the terminal who voted what and with what percentage.
In the body variable there is the typical discovery-it comment.
If you want to reuse it, you will have to replace the name of your voting account in place of 'discover-it'.
Otherwise he does nothing and waits 30 seconds before leaving.
If there is an exception of the RPCError type, the program pauses for 30 seconds then restarts.

Well and that's all, see you next time !!


[ITA]

Introduzione

Sono felice di informare la community di Discovery-it che da circa una settimana a questa parte è in funzione un bot per la curation dei post.
Il suo funzionamento è molto semplice ed è a disposizione dei curatori di Discovery-it.
Per realizzarlo mi sono ispirato al comando !BEER di beerlover@beerlover e al comando tipu@tipu curate di tipu@tipu.
Infatti quando un curatore vuole votare un post con la trail di discovery-it, deve semplicemente commentare sotto al post con il comando !discovery 30 , dove 30 sta ad indicare la percentuale di voto. Ovviamente la percentuale può anche essere diversa, per adesso sono ammessi valori compresi tra 30% e 50%
Inoltre si può inserire questo comando anche all'interno di un commento, così da poter creare dei commenti più articolati e simpatici. Ad esempio potrei scrivere: "Complimenti un !discovery 50 è ciò che ti meriti" o qualsiasi altra cosa.

Come funziona

  • Innanzitutto l'uso di questo bot è riservato ai curatori di discovery-it quindi al suo interno è contenuta una lista con gli username dei curatori.

  • Ogni 30 secondi il bot legge l'ultimo commento fatto dai curatori e controlla due cose:
    1) se all'interno del commento è contenuto il comando !discovery 30 e che il comando sia ben posto.
    La sintassi corretta è !discovery+spazio+numero
    Il numero deve essere compreso tra 30 e 50 e deve essere un numero intero
    2) se l'account discovery-it@discovery-it ha già votato il post sotto al quale compare il comando.

  • Nel caso in cui il comando viene trovato e l'account discovery-it@discovery-it non ha votato il post, il bot vota il post e commenta con il classico commento di discovery. Altrimenti non fa niente e aspetta 30 secondi per un nuovo controllo.

Il codice

Lo script è scritto nel linguaggio Python ed usa la libreria ufficiale di hive, adattada per hive da pharesim@pharesim. Se siete interessati la potete trovare qui.
Ora vi mostrerò passo passo come si struttura il codice e sarei grato se qualche utente più esperto di me mi possa dare qualche consiglio su come migliorare lo script.

1) Importiamo i moduli necessari al funzionamento

import string
import random
import time
from hive import Hive
from hive.hived import Hived
from hive.post import Post
from hive.account import Account
from hivebase.exceptions import RPCError 

2) Inizializziamo la lista dei curatori e dei nodi di Hive

curatori = ['curatore1','curatore2','curatore3']
hived_nodes = ['https://api.hive.blog','https://anyx.io','http://anyx.io','https://api.hivekings.com']

Ovviamente al posto di curatore1-2-3 mettete i nomi dei vostri curatori, inoltre potete sempre aggiungere altri curatori e altri nodi. Basterà modificare queste linee di codice e poi salvare il file.
Per avere una lista dei nodi aggiornata e funzionante potete consultare i post dell'account fullnodeupdate@fullnodeupdate

3) Creiamo l'oggetto Hive con la lista dei nodi e la posting key privata dell'account che voterà, in questo caso discovery-it@discovery-it

s = Hive(nodes = hived_nodes,keys = ['posting key privata'])

Chiaramente al posto di 'posting key privata' sostituite la vera posting key privata.

4) Definiamo alcune funzioni necessarie al funzionamento

def estrai_identifier(url):
    ini = url.find('@') + 1
    fine = url.find('#')
    return url[ini:fine]

def estrai_percentuale(comm,comando):
    ini = comm.find(comando)
    comm = comm[ini:]
    num = ''
    for i in range(len(comando),len(comm)):
        if comm[i].isdigit() == True:
            num = num + comm[i]
    if comm.find(num) == -1: return ''  
    return num

def check_perc(perc):
    if perc == '': return False
    elif int(perc) > 50 or int(perc) <= 29: return False
    else: return True

La funzione estrai_identifier a partire dall'url del post estrae l'identifier del post, cioè la stringa "author/permlink"

La funzione estrai_percentuale è quella che si occupa di estrarre la percentuale di voto scelta dal curatore.
Scarta eventuali numeri con la virgola restituendo una stringa vuota. Ritorna una stringa vuota anche nel caso nessun numero sia presente. Altrimenti ritorna il numero relativo alla percentuale.

La funzione check_perc invece controlla se la percentuale di voto è compresa tra 30% e 50%

Dunque queste ultime due funzioni verificano che il comando sia ben posto.

5) Creiamo un lista di query da passare alla funzione get_discussion_by_comments per estrarre informazioni dalla blockchain sull'ultimo commento fatto dai curatori.
query_list = []
for curator in curatori:
    query_list.append({"limit":1,"start_author":curator})

Qui "limit":1 dice alla blockchain quanti commenti vogliamo, in questo caso solo 1, l'ultimo. Se al posto di 1 mettiamo 3 vedremo gli ultimi 3 commenti fatti da un determinato utente.

Bene ora vediamo il nucleo centrale del programma, tutto contenuto in un blocco "try except" al fine di gestire le eventuali eccezioni di solito causate da problemi di connessione ai nodi.

6) La parte principale

while True:
    try :
        dict_list,comment_list,url_list,identifier_list = [],[],[],[]
        for i in range(len(curatori)):
            dict_list.append(s.hived.get_discussions_by_comments(query_list[i])[0]) 
            comment_list.append(dict_list[i]['body'])
            url_list.append(dict_list[i]['url'])    
            identifier_list.append(estrai_identifier(url_list[i]))      

Per ogni curatore esegue una query alla blockchain tramite la funzione get_discussion_by_comments e dall'ultimo commento fatto estrae 3 liste: una per i commenti, una per gli url dei post, e un'altra per gli identifier.

        a = Account('discovery-it')
        index = -1
        comando_trovato = ''
        comando = '!discovery '
        for i in range(len(comment_list)):
            if comment_list[i].find(comando) != -1 and a.has_voted(Post(identifier_list[i])) == False:
                index = i   
                comando_trovato = comment_list[i]
                break

Crea l'oggetto Account per il nostro account votante e definisce il comando da cercare, cioè !discovery. Quindi controlla se nella lista dei commenti è presente il comando e se il nostro account non ha votato il post. Se l'esito è positivo registra in due variabili il commento in questione e il suo indice nella lista.

        if index != -1:
            perc = estrai_percentuale(comando_trovato,comando)
            if check_perc(perc) == True:
                perc = float(perc)
                s.commit.vote(identifier_list[index],perc,'discovery-it')
                body = '
https://cdn.steemitimages.com/DQmTAn3c753LR7bHCLPo96g9UvRMaPFwaMYn8VQZa85xczC/discovery_logo_colore%20-%20Copia.png

\n\nQuesto post è stato condiviso e votato all\'interno del discord del team curatori di discovery-it Entra nella nostra community! [hive-193212](https://hive.blog/trending/hive-193212)\nThis post was shared and voted inside the discord by the curators team of discovery-it. Join our community! [hive-193212](https://hive.blog/trending/hive-193212)
'
permlink = ''.join(random.choices(string.digits+string.ascii_lowercase,k=10)) s.commit.post(title='',body=body,author='discovery-it',permlink=permlink,reply_identifier=identifier_list[index]) print(curatori[index]+' ha curato '+identifier_list[index]+' al '+str(perc)+'%') time.sleep(30) except RPCError: print('Problema di connessione ai nodi, aspetto 30 secondi e riparto') time.sleep(30)

Adesso se il comando è stato trovato, il codice controlla che questo sia ben posto ed in caso affermativo vota e commenta il post creando un permlink casuale di 10 caratteri. Inoltre ci scrive nel terminale chi ha votato cosa e con quale percentuale.
Nella variabile body è presente il tipico commento di discovery-it.
Se volete riutilizzarlo dovrete sostituire al posto di 'discover-it' il nome del vostro account votante.
Altrimenti non fa nulla e aspetta 30 secondi prima di ripartire.
Nel caso si presentasse una eccezione del tipo RPCError il programma va in pausa per 30 secondi poi riparte.

Bene e con questo è tutto, alla prossima!!

Discovery-it Curation Bot just born and how it works [ENG/ITA] | Ecency