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): logging.info(f'"{f.__name__}" called by {args[0].effective_chat.username}') return f(*args, **kwargs) return decorated_function 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].effective_chat.id): 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 def register(update, context): uid = update.effective_chat.id un = update.effective_chat.username 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 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.effective_chat.username: 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.effective_chat.id) 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.effective_chat.username} has tipped @{target_un} {amount} WOW!') 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 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 = 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.effective_chat.id) 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 # transfer funds to given address try: tx = wownero.Wallet().transfer(dest_address=address, amount=amount, priority=2, account=u.account_index) print(tx) update.message.reply_text(f'@{update.effective_chat.username} has tipped @{target_un} {amount} WOW!') 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 def balance(update, context): u = db.User.get(telegram_id=update.effective_chat.id) balances = wownero.Wallet().balances(account=u.account_index) update.message.reply_text(f'Available balance for {update.effective_chat.username}: {balances[1]} ({balances[0]} locked)') @wallet_rpc_required @registration_required @log_event def deposit(update, context): u = db.User.get(telegram_id=update.effective_chat.id) address = wownero.Wallet().addresses(account=u.account_index)[0] update.message.reply_text(f'Deposit address for {update.effective_chat.username}: {address}') @wallet_rpc_required @log_event def debug(update, context): if is_tg_admin(update.effective_chat.id): # 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") 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 ', 'help': 'Tip a user in Wownero' }, 'send': { 'func': send, 'example': '/send
', '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 } }