tg-bot/tipbot/commands.py

264 lines
9.1 KiB
Python
Raw Normal View History

2020-07-20 16:26:04 +00:00
import wownero
import config
import logging
import db
import six
from functools import wraps
from decimal import Decimal
def log_event(f):
@wraps(f)
def decorated_function(*args, **kwargs):
msg = args[0].message
logging.info(f'"{f.__name__}" invoked from {msg.from_user["username"]} - Full command: "{msg.text}"')
return f(*args, **kwargs)
return decorated_function
2020-07-20 16:26:04 +00:00
def wallet_rpc_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
wallet = wownero.Wallet()
if not wallet.connected:
logging.error(f'Wallet RPC interface is not available: {args[0].message}')
args[0].message.reply_text('Wallet RPC interface is not available right now. Try again later.')
return False
return f(*args, **kwargs)
return decorated_function
def registration_required(f):
@wraps(f)
def decorated_function(*args, **kwargs):
wallet = wownero.Wallet()
if not db.User.filter(telegram_id=args[0].message.from_user['id']):
2020-07-20 16:26:04 +00:00
args[0].message.reply_text('You are not yet registered. Issue the /register command.')
return False
return f(*args, **kwargs)
return decorated_function
def help(update, context):
commands = list()
for i in all_commands:
pk = all_commands[i]
if not pk.get('admin', False):
commands.append('{example} - {help}'.format(
example=pk['example'],
help=pk['help']
))
update.message.reply_text('Here are the available commands for this bot:\n\n' + '\n\n'.join(commands))
@wallet_rpc_required
@log_event
2020-07-20 16:26:04 +00:00
def register(update, context):
uid = update.message.from_user['id']
un = update.message.from_user['username']
2020-07-20 16:26:04 +00:00
if db.User.filter(telegram_id=uid):
update.message.reply_text('You are already registered.')
else:
wallet = wownero.Wallet()
try:
account_index = wallet.new_account(label=un)
except Exception as e:
logging.error(f'Unable to create a new account in wallet RPC: {e}. Debug: {update.message}')
update.message.reply_text('Unable to create a new account for you. Ask for help.')
return False
try:
u = db.User(
telegram_id=uid,
telegram_user=un,
account_index=account_index,
)
u.save()
reply_text = [
'You have been registered and can now send and receive tips.',
'Ask for /help to see all available bot commands.'
]
update.message.reply_text(' '.join(reply_text))
except Exception as e:
logging.error(f'Unable to register user in DB: {e}. Debug: {update.message}')
update.message.reply_text('Unable to create a new account for you. Ask for help.')
return False
@wallet_rpc_required
@registration_required
@log_event
2020-07-20 16:26:04 +00:00
def tip(update, context):
if len(context.args) < 2:
update.message.reply_text('Not enough arguments passed.')
return False
elif len(context.args) == 2:
message = ""
elif len(context.args) > 2:
message = context.args[2:]
# validate target user
if context.args[0].startswith('@'):
target_un = context.args[0][1:]
else:
target_un = context.args[0]
if target_un == update.message.from_user['username']:
2020-07-20 16:26:04 +00:00
update.message.reply_text('You cannot tip yourself!')
return False
if not db.User.filter(telegram_user=target_un):
reply_text = [
'That user has not registered and cannot receive tips yet.',
'If they would like to receive a tip, have them /register with the bot.'
]
update.message.reply_text(' '.join(reply_text))
return False
# validate amount
try:
amount = Decimal(context.args[1])
except:
update.message.reply_text(f'Bad Wownero amount specified; "{context.args[1]}" is not a valid number.')
return False
if amount < 1:
update.message.reply_text('Bad Wownero amount specified. Provide only positive integers or decimals greater than or equal to 1.')
return False
tipper = db.User.get(telegram_id=update.message.from_user['id'])
2020-07-20 16:26:04 +00:00
tipper_balances = wownero.Wallet().balances(account=tipper.account_index)
if amount > tipper_balances[1]:
update.message.reply_text(f'You do not have sufficient funds to send {amount} WOW. Check your /balance')
return False
# get target user details
u = db.User.get(telegram_user=target_un)
address = wownero.Wallet().addresses(account=u.account_index)[0]
# transfer funds to user
try:
tx = wownero.Wallet().transfer(dest_address=address, amount=amount, priority=2, account=u.account_index)
print(tx)
update.message.reply_text(f'@{update.message.from_user["username"]} has tipped @{target_un} {amount} WOW!')
2020-07-20 16:26:04 +00:00
except Exception as e:
logging.error(f'Unable to send transfer: {e}. Debug: {update.message}')
update.message.reply_text('Failed to send a tip. Ask for help.')
@wallet_rpc_required
@registration_required
@log_event
2020-07-20 16:26:04 +00:00
def send(update, context):
if len(context.args) < 2:
update.message.reply_text('Not enough arguments passed.')
return False
# validate address
if len(context.args[0]) in [97, 107]:
address = context.args[0]
else:
update.message.reply_text('This does not look like a valid Wownero address. Try again.')
return False
# validate amount
try:
amount = wownero.as_wownero(context.args[1])
2020-07-20 16:26:04 +00:00
except:
update.message.reply_text(f'Bad Wownero amount specified; "{context.args[1]}" is not a valid number.')
return False
if amount < 1:
update.message.reply_text('Bad Wownero amount specified. Provide only positive integers or decimals greater than or equal to 1.')
return False
2020-07-21 17:41:24 +00:00
sender = db.User.get(telegram_id=update.message.from_user['id'])
sender_balances = wownero.Wallet().balances(account=sender.account_index)
if amount > sender_balances[1]:
2020-07-20 16:26:04 +00:00
update.message.reply_text(f'You do not have sufficient funds to send {amount} WOW. Check your /balance')
return False
# transfer funds to given address
try:
2020-07-21 17:41:24 +00:00
tx = wownero.Wallet().transfer(dest_address=address, amount=amount, priority=2, account=sender.account_index)
update.message.reply_text(f'Sent {amount} WOW! Tx: {tx}')
2020-07-20 16:26:04 +00:00
except Exception as e:
logging.error(f'Unable to send transfer: {e}. Debug: {update.message}')
2020-07-21 17:41:24 +00:00
update.message.reply_text('Failed to send Wownero. Ask for help.')
2020-07-20 16:26:04 +00:00
@wallet_rpc_required
@registration_required
@log_event
2020-07-20 16:26:04 +00:00
def balance(update, context):
u = db.User.get(telegram_id=update.message.from_user['id'])
2020-07-20 16:26:04 +00:00
balances = wownero.Wallet().balances(account=u.account_index)
2020-07-21 07:12:13 +00:00
update.message.reply_text(f'Available balance for {update.message.from_user["username"]}: {float(balances[1])} WOW ({float(balances[0])} WOW locked)')
2020-07-20 16:26:04 +00:00
@wallet_rpc_required
@registration_required
@log_event
2020-07-20 16:26:04 +00:00
def deposit(update, context):
u = db.User.get(telegram_id=update.message.from_user['id'])
2020-07-20 16:26:04 +00:00
address = wownero.Wallet().addresses(account=u.account_index)[0]
update.message.reply_text(f'Deposit address for {update.message.from_user["username"]}: {address}')
2020-07-20 16:26:04 +00:00
@wallet_rpc_required
@log_event
2020-07-20 16:26:04 +00:00
def debug(update, context):
if is_tg_admin(update.message.from_user['id']):
2020-07-20 16:26:04 +00:00
# tx = wownero.Wallet().transfer(
# dest_address='WW2vmEGV68ZFeQWwPEJda3UcdWCPfWBnDK1Y6MB9Uojx9adBhCxfx9F51TomRjmD3z7Gyogie3mfVQEkRQjLxqbs1KMzaozDw',
# amount=Decimal(2),
# priority=2,
# account=0
# )
# update.message.reply_text(str(tx))
# balances = wownero.Wallet().balances(account=0)
# addresses = wownero.Wallet().addresses(account=0)
# accounts = wownero.Wallet().accounts()
# a = []
# for i in accounts:
# a.append(str(wownero.Wallet().balances(account=i)[1]))
update.message.reply_text('sup lza')
2020-07-20 16:26:04 +00:00
else:
update.message.reply_text('you cant do that.')
def is_tg_admin(chat_id):
if chat_id == config.TG_ADMIN_ID:
return True
else:
return False
all_commands = {
'tip': {
'func': tip,
'example': '/tip <username> <amount> <message>',
'help': 'Tip a user in Wownero'
},
'send': {
'func': send,
'example': '/send <address> <amount>',
'help': 'Send Wownero to a specified Wownero address'
},
'balance': {
'func': balance,
'example': '/balance',
'help': 'Show your current balance'
},
'register': {
'func': register,
'example': '/register',
'help': 'Register your Telegram user ID to this bot to begin sending and receiving tips',
},
'deposit': {
'func': deposit,
'example': '/deposit',
'help': 'Show your Wownero wallet address for transferring funds to'
},
'help': {
'func': help,
'example': '/help',
'help': 'Show available commands for the bot',
},
'debug': {
'func': debug,
'admin': True
}
}