Skip to content
Browse files

BANANO-ify and more

- Rewrite DB layer to use peewee ORM with a pooled postgres database
- Use eventlet green-threads instead of pre-fork strategy for concurrency
- Some other minor things, like adding use_peers to work_generate
  • Loading branch information...
bbedward committed Feb 19, 2019
1 parent 327e294 commit 4ec2a1cf97b0d26ab6f41dc6c141ebf848f60d05
Showing with 356 additions and 528 deletions.
  1. +11 −9
  2. +37 −44 modules/
  3. +47 −187 modules/
  4. +178 −220 modules/
  5. +14 −14 modules/
  6. +4 −3 requirements.pip
  7. +15 −0 tipbot.service
  8. +50 −51
@@ -1,17 +1,19 @@
NOS Telegram Tip Bot
# BANANO Telegram Tip Bot


Thank you for using my services @NOSTipBot! Below is a list of commands, and a description of how you can interact with me:
- .tip
- .help
- .register
- .account
- .withdraw

• !help: The NOSTipBot will respond to your DM with a list of commands and their functions. If you forget something, use this to get a hint of how to do it!n
# Install

• !register: Creates a fresh NOS (XNOS) account address specifically for you. This is used to store your tips. Make sure to withdraw to a private wallet, as the tip bot is not meant to be a long term storage device for NOS (XNOS).
`cp config/example_config.ini config/webhooks.ini`

• !balance: This shows you how much funds are in your your account.
Specify postgres user/schema/port/host

• !tip: Tips are sent directly to @username on telegram. Tag @NOSTipBot and mention !tip <amount> <@username>. EXAMPLE: @NOSTipBot !tip 1 @user will send a 1 NOS (XNOS) tip to another user.
Copy tipbot.service example to systemd

• !account: Returns the account number. You can use this to deposit more NOS (XNOS) to tip from your personal wallet.

• !withdraw: Proper usage is !withdraw nos_12345. This will send the full balance of your tip account to another external NOS (XNOS) account. Optional: You can include an amount to withdraw by sending !withdraw <amount> <address>. Example: !withdraw 1 nos_123 would withdraw 1 Nos to account nos_123
Run with systemd
@@ -8,7 +8,8 @@
import nano
import requests

from . import db, social
import db
import social

# Read config and parse constants
config = configparser.ConfigParser()
@@ -20,23 +21,23 @@

# Connect to Nano node
rpc = nano.rpc.Client(NODE_IP)
raw_denominator = 10**10
raw_denominator = 10**29

def receive_pending(sender_account):
Check to see if the account has any pending blocks and process them
try:"{}: in receive pending".format("{}: in receive pending".format(datetime.utcnow()))
pending_blocks = rpc.pending(account='{}'.format(sender_account))"pending blocks: {}".format(pending_blocks))
if len(pending_blocks) > 0:
for block in pending_blocks:
work = get_pow(sender_account)
if work == '':"{}: processing without pow".format(
receive_data = {
'action': "receive",
'wallet': WALLET,
@@ -45,7 +46,7 @@ def receive_pending(sender_account):
else:"{}: processing with pow".format(
receive_data = {
'action': "receive",
'wallet': WALLET,
@@ -56,10 +57,10 @@ def receive_pending(sender_account):
receive_json = json.dumps(receive_data)'{}'.format(NODE_IP), data=receive_json)"{}: block {} received".format(, block))
datetime.utcnow(), block))

else:'{}: No blocks to receive.'.format('{}: No blocks to receive.'.format(datetime.utcnow()))

except Exception as e:"Receive Pending Error: {}".format(e))
@@ -72,25 +73,25 @@ def get_pow(sender_account):
Retrieves the frontier (hash of previous transaction) of the provided account and generates work for the next block.
""""{}: in get_pow".format("{}: in get_pow".format(datetime.utcnow()))
account_frontiers = rpc.accounts_frontiers([sender_account])
frontier_hash = account_frontiers[sender_account]
except Exception as e:"{}: Error checking frontier: {}".format(, e))
datetime.utcnow(), e))
return ''"account_frontiers: {}".format(account_frontiers))

work = ''"{}: hash: {}".format(, frontier_hash))"{}: hash: {}".format(datetime.utcnow(), frontier_hash))
while work == '':
work = rpc.work_generate(frontier_hash)"{}: Work generated: {}".format(, work))
work = rpc.work_generate(frontier_hash, use_peers=True)"{}: Work generated: {}".format(datetime.utcnow(), work))
except Exception as e:"{}: ERROR GENERATING WORK: {}".format(, e))
datetime.utcnow(), e))

return work
@@ -101,42 +102,36 @@ def send_tip(message, users_to_tip, tip_index):
Process tip for specified user
""""{}: sending tip to {}".format(, users_to_tip[tip_index]['receiver_screen_name']))
datetime.utcnow(), users_to_tip[tip_index]['receiver_screen_name']))
if str(users_to_tip[tip_index]['receiver_id']) == str(
self_tip_text = "Self tipping is not allowed. Please use this bot to spread the NOS to other users!"
self_tip_text = "Self tipping is not allowed. Please use this bot to tip BANANO to other users!"
social.send_reply(message, self_tip_text)"{}: User tried to tip themself").format("{}: User tried to tip themself").format(datetime.utcnow())

# Check if the receiver has an account
receiver_account_get = "SELECT account FROM users where user_id = %s"
arguments = (int(users_to_tip[tip_index]['receiver_id']))
receiver_account_data = db.get_db_data(receiver_account_get, arguments)

# If they don't, create an account for them
if not receiver_account_data:
user = == int(users_to_tip[tip_index]['receiver_id'])).get()
users_to_tip[tip_index]['receiver_account'] = user.account
except db.User.DoesNotExist:
# If they don't, create an account for them
users_to_tip[tip_index]['receiver_account'] = rpc.account_create(
wallet="{}".format(WALLET), work=True)
create_receiver_account = (
"INSERT INTO users (user_id, user_name, account, register) "
"VALUES({}, '{}', '{}',0)".format(
user = db.User(
user_id = int(users_to_tip[tip_index]['receiver_id']),
user_name = users_to_tip[tip_index]['receiver_screen_name'],
account = users_to_tip[tip_index]['receiver_account'],
"{}: Sender sent to a new receiving account. Created account {}".

users_to_tip[tip_index]['receiver_account'] = receiver_account_data[0][

# Send the tip

message['tip_id'] = "{}{}".format(message['id'], tip_index)

work = get_pow(message['sender_account'])
@@ -185,19 +180,17 @@ def send_tip(message, users_to_tip, tip_index):

# Send a DM to the receiver
receiver_tip_text = (
"@{} just sent you a {} NOS tip! Reply to this DM with !balance to see your new balance. If you have not "
"registered an account, send a reply with !register to get started, or !help to see a list of "
"commands! Learn more about NOS (XNOS) & Nollar at"
.format(message['sender_screen_name'], message['tip_amount_text'],
"@{0} just sent you a {1} BANANO tip! Reply to this DM with .balance to see your new balance. If you have not "
"registered an account, send a reply with .register to get started, or .help to see a list of "
"commands! Learn more about BANANO at"
.format(message['sender_screen_name'], message['tip_amount_text']))

except Exception as e:
.format(, e))
.format(datetime.utcnow(), e))"{}: tip sent to {} via hash {}".format(, users_to_tip[tip_index]['receiver_screen_name'],
datetime.utcnow(), users_to_tip[tip_index]['receiver_screen_name'],
Oops, something went wrong.

0 comments on commit 4ec2a1c

Please sign in to comment.
You can’t perform that action at this time.