from subprocess import check_output
import requests
import json
import os
import time
import random
import datetime
import telepot
from telepot.loop import MessageLoop
import telepot.api
import urllib3
import logging
'''
This script is based on the tutorial:
http://www.instructables.com/id/Set-up-Telegram-Bot-on-Raspberry-Pi/
'''
### configure gloabls here
MONITOR_TX_ADDR = True # enable tx address monitoring on cryptoid.info
main_loop_cycle = 120 # time in seconds
bot_api_key = "524648907:AAFYnphAtSQelw5u22ejsKvt2PiE5x5zBUw"
access_ids = [ 310989044, ] # array of user ids that can communicate with the bot
master_chat_id = 310989044 # the chat id of the master that gets security notifications
pivx_cli_dir = "/home/pivx" # location of pivx-cli
check_staking_dir = "/home/pivx" # location of check_staking.sh
logfile = "bot.err" # name of the logfile
if MONITOR_TX_ADDR:
cryptoid_id = 353908 # magic?! id to get all transactions from cryptoid.info for the adress below
tx_address = "DDyN3knkxb6U7dwmnqvhhAyt4AwRjsbASJ"
# set up logger
logging.basicConfig(filename=logfile,level=logging.INFO)
# enable retry mechanism in connection pool
telepot.api._pools = {
'default': urllib3.PoolManager(num_pools=3, maxsize=10, retries=3, timeout=30),
}
def sendMessageRetry(chat_id, msg, retry_limit = 3, parse_mode=""):
# the ugly retry mechanism should not be necessary, but time will tell...
for x in range(0, retry_limit):
try:
bot.sendMessage(chat_id, msg, parse_mode=parse_mode)
return
except Exception as e:
logging.warning("Error sending message (%s)" % str(e))
time.sleep(2)
logging.error("Couldn't send message, tried %d times" % retry_limit)
def pivxGetLastTransaction(id):
url = "https://chainz.cryptoid.info/explorer/address.tx.dws?coin=pivx&id=%d" % id
response = requests.post(url)
if response.ok:
transactions = str(response.content)[2:-4].split("],[")
t = transactions[0].split(",") # grab last transaction
tx_hash = t[1].replace("\"", "")
amount = t[4]
return (tx_hash, float(amount))
else:
raise Exception("Error in pivxGetLastTransaction occured: %s" % str(response))
def pivxGetAccountBalance():
j = json.loads(pivxGetInfo())
return j["balance"]
def pivxGetInfo():
try:
os.chdir(pivx_cli_dir)
return str(check_output(["./pivx-cli", "getinfo"]))
except CalledProcessError:
raise Exception("Error while executing `%s/pivx-cli getinfo` occured" % pivx_cli_dir)
def pivxCheckStaking():
try:
os.chdir(check_staking_dir)
return str(check_output(["./check_staking.sh", ""]))
except CalledProcessError:
raise Exception("Error while executing `%s/check_staking.sh` occured" % check_staking_dir)
def printHelp(chat_id):
msg = "";
msg += "/help - display this help.\r\n"
msg += "/pivxinfo - reply with output of `pivx-cli getinfo`.\r\n"
msg += "/pivxstaking - reply with output of `check_staking.sh`.\r\n"
msg += "/roll - reply with a random integer between 1 and 6, like rolling a dice.\r\n"
msg += "/time - reply with the current time, like a clock.\r\n"
sendMessageRetry(chat_id, msg, parse_mode='Markdown')
def handle(msg):
chat_id = msg['chat']['id']
command = msg['text']
print 'Got command: %s' % command
if msg['from']['id'] not in access_ids:
sendMessageRetry(chat_id, "Access denied")
sendMessageRetry(master_chat_id, "Access violation detected: %s" % str(msg))
return
try:
if command == '/help':
printHelp(chat_id)
elif command == '/pivxinfo':
sendMessageRetry(chat_id, pivxGetInfo())
elif command == '/pivxstaking':
sendMessageRetry(chat_id, pivxCheckStaking())
elif command == '/roll':
sendMessageRetry(chat_id, random.randint(1,6))
elif command == '/time':
sendMessageRetry(chat_id, str(datetime.datetime.now()))
else:
sendMessageRetry(chat_id, "I did not understand you. Type /help for a list of supported commands.")
except Exception as e:
msg = "Error in handle() occurred: %s" % str(e)
logging.error(msg)
sendMessageRetry(chat_id, msg)
bot = telepot.Bot(bot_api_key)
MessageLoop(bot, handle).run_as_thread()
print 'I am listening ...'
old_balance = None
if MONITOR_TX_ADDR is True:
old_tx_hash = None
while 1:
try:
# initialization - do this only once at the beginning
# NB: we do it inside the loop in case it fails at the first time
if old_balance is None:
old_balance = pivxGetAccountBalance()
logging.info("Initial balance is: %f" % old_balance)
if MONITOR_TX_ADDR is True and old_tx_hash is None:
old_tx_hash, old_tx_amount = pivxGetLastTransaction(cryptoid_id)
logging.info("Initial transaction is: %s %f" % (old_tx_hash, old_tx_amount))
time.sleep(main_loop_cycle)
# do this only if initialization above was successful
if old_balance is not None:
# handle (changed) account balance
new_balance = pivxGetAccountBalance()
diff = new_balance - old_balance
if diff != 0:
msg = "*Account balance changed* by %f piv" % diff
logging.info(msg)
sendMessageRetry(master_chat_id, msg, parse_mode='Markdown')
old_balance = new_balance
# do this only if initialization above was successful
if MONITOR_TX_ADDR is True and old_tx_hash is not None:
# handle (new) transactions
new_tx_hash, new_tx_amount = pivxGetLastTransaction(cryptoid_id)
if new_tx_hash != old_tx_hash:
msg = "*New transaction* on [address](http://www.presstab.pw/phpexplorer/PIVX/address.php?address=%s) detected. Tx amount = %f piv" % (tx_address, new_tx_amount)
logging.info(msg)
sendMessageRetry(master_chat_id, msg, parse_mode='Markdown')
old_tx_hash = new_tx_hash
except Exception as e:
msg = "Error in main loop occurred: %s" % str(e)
logging.error(msg)
sendMessageRetry(chat_id, msg)