Writing a Hive bot with beem

Introduction

Something I have wanted to do for a while was to try creating a bot that can respond to Hive posts based on some criteria. The idea for a project came about when I noticed that some people had mis-spelled the #proofofbrain tag. And so @proofofbrian was born!

To implement this I made use of the beem library. I have used this before to compile my #BritList posts, but that was a read-only process. It does seem the project creator @holger80 has been absent for a while, but others are maintaining it. I had a lot of help from @foxon in the Discord channel. Part of the problem was that I was using an old version. I use the Anaconda build of Python on Ubuntu and that was not finding the very latest version using the conda package manager, but I could get it using pip. Before I updated I was getting various errors when trying to use the account posting key, so that is something to check.

What I wanted to achieve was:

  • Check the post stream for those using the #proofofbrian tag.
  • Leave a comment and a small vote.
  • Log the user so they would not get this comment again.

There are various ways to avoid putting a private key in your code, but I opted for a local text file. beem can encrypt it if you prefer. Even if I exposed it the posting key of a low value account is not too useful.

I have another file for logging people who have been notified of their mistake. I was going to put animated GIFs in the comments, but used some images from Wikimedia instead. One issue I have not resolved is that the random picker seems to keep getting the same one.

Otherwise it seems to be working fine. I did do some tests such as creating comments against my own posts that I could just delete.

You can see the script is pretty short. beem does all the heavy lifting of blockchain operations. I tested it in Jupyter Notebook as it is convenient for playing around with things like this.

I am not sure if Hive really needs this particular bot. There are only a few such posts each day and I would hope people would take the hint, especially if they actually want the POB tokens. I could probably run it on a Raspberry Pi to have it up all the time. I may try that anyway. For now I have just run it during the day.

I hope others can gain some value from this. There are some links below to posts that inspired and informed me.

Please let me know if there are better ways to do any of this.

The Code

#!/usr/bin/env python
# coding: utf-8

from datetime import datetime, timedelta, date
from beem import Hive
from beem.account import Account
from beem.amount import Amount
from beem.blockchain import Blockchain
from beem.comment import Comment
from beem.exceptions import ContentDoesNotExistsException
from beem.instance import set_shared_blockchain_instance
import random

notified = []
with open('notified.txt','r') as f:
    for l in f:
        notified.append(l.strip())
        
posting = ''
with open('posting.txt','r') as f:
    for l in f:
        posting = l.strip()
        
postacc = 'proofofbrian'

hive = Hive(node=['https://api.hive.blog'], keys={'posting':posting})
set_shared_blockchain_instance(hive)
chain = Blockchain()

gifs=[
    {'Pic':', 'Source':'}, 
    {'Pic':', 'Source':'}, 
    {'Pic':','Source':'},
    {'Pic':', 'Source':'},
    {'Pic':', 'Source':'}
]

def addComment(comm):
    image = random.choice(gifs)
    text = f'''Here is your Proof of Brian. I think you meant #ProofOfBrain
![Brian]({image["Pic"]})
[Source]({image["Source"]})'''
    comm.reply(body=text,author=postacc)
    #return text

tracktag = 'proofofbrian'
while True:
    try:
        for post in chain.stream(opNames="comment", threading=True, thread_num=5):
            author = post['author']
            c = Comment(post)
            if c.is_main_post() and tracktag in post['tags'] and author not in notified:
                print('Found one', author,post['title'], post['timestamp'])
                print(post['tags'])
                addComment(c)
                c.upvote(voter=postacc)
                notified.append(author)
                with open('notified.txt', 'a') as f:
                    f.write(f'{author}\n')
    except Exception as error:
        print(repr(error))
        continue

Reference

H2
H3
H4
3 columns
2 columns
1 column
15 Comments