def return_tips(): tips_to_return_call = ("SELECT tip_bot.tip_list.dm_id, tip_bot.tip_list.sender_id, " "tip_bot.users.account, tip_bot.tip_list.amount " "FROM tip_bot.tip_list " "INNER JOIN tip_bot.users " "ON tip_bot.tip_list.receiver_id = tip_bot.users.user_id " "WHERE DATE(tip_bot.tip_list.timestamp) < DATE_SUB(now(), interval 30 day) " "AND tip_bot.users.register = 0 " "AND tip_bot.tip_list.processed = 2;") tip_list = get_db_data(tips_to_return_call) for tip in tip_list: transaction_id = tip[0] sender_id = tip[1] receiver_account = tip[2] amount = Decimal(tip[3]) logging.info("{}: Returning tip {}".format(datetime.now(), transaction_id)) sender_account_call = "SELECT account FROM users WHERE user_id = {}".format(sender_id) sender_account_info = get_db_data(sender_account_call) sender_account = sender_account_info[0][0] send_amount = int(amount * 1000000000000000000000000000000) receive_pending(receiver_account) work = get_pow(receiver_account) try: if work == '': send_hash = rpc.send(wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(sender_account), amount=send_amount) else: send_hash = rpc.send(wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(sender_account), amount=send_amount, work=work) logging.info("{}: Tip returned under hash: {}".format(str(datetime.now()), send_hash)) except nano.rpc.RPCException as e: logging.info("{}: Insufficient balance to return. Descriptive error: {}".format(datetime.now(), e)) insufficient_balance_call = ("UPDATE tip_bot.tip_list " "SET processed = 6 " "WHERE dm_id = %s;") insufficient_balance_values = [transaction_id,] set_db_data(insufficient_balance_call, insufficient_balance_values) continue except Exception as f: logging.info("{}: Unexpected error: {}".format(datetime.now(), f)) continue update_tip_call = ("UPDATE tip_bot.tip_list " "SET processed = 9 " "WHERE dm_id = %s;") update_tip_values = [transaction_id,] try: set_db_data(update_tip_call, update_tip_values) except Exception as e: logging.info("{}: Error updating tip to returned: {}".format(datetime.now(), e)) send_returned_notice_to_receivers() send_returned_notice_to_senders()
def return_unused_balance(): get_inactive_users = ( "SELECT user_id, system, account " " FROM tip_bot.return_address " " WHERE last_action < DATE_SUB(now(), interval 60 day) " " AND account IS NOT NULL;") inactive_users = get_db_data(get_inactive_users) logging.info("{}: Returning inactive balances for user list: {}".format( datetime.now(), inactive_users)) for user in inactive_users: get_tip_account = ("SELECT account FROM users " "WHERE user_id = {} AND system = '{}'".format( user[0], user[1])) tip_account_data = get_db_data(get_tip_account) tip_account = tip_account_data[0][0] print("Returning unused balance for user {} system {} account {} to ") # check for any unreceived tips receive_pending(tip_account) # get balance of tip account balance_data = {'action': 'account_balance', 'account': tip_account} json_request = json.dumps(balance_data) r = requests.post('{}'.format(NODE_IP), data=json_request) rx = r.json() balance_raw = rx['balance'] balance = Decimal(balance_raw) / CONVERT_MULTIPLIER[CURRENCY] # send from tip account to return account if Decimal(balance) > 0: try: donation_amount, send_amount = calculate_donation_amount( Decimal(balance), user[0], user[1]) work = get_pow(tip_account) donation_hash = rpc.send(wallet=WALLET, source=tip_account, destination=BOT_ACCOUNT, work=work, amount=donation_amount) work = get_pow(tip_account) inactive_hash = rpc.send(wallet=WALLET, source=tip_account, destination=user[2], work=work, amount=send_amount) except Exception as e: logging.info("{}: ERROR: {}".format(datetime.now, e)) logging.info( "{}: Inactive user {} on {} had their funds returned to their recovery address {} under hash {}" .format(datetime.now(), user[0], user[1], user[2], inactive_hash)) logging.info( "{}: Inactive user {} on {} donated under hash {}".format( datetime.now(), user[0], user[1], user[2], donation_hash)) else: logging.info("{}: Balance for user {} on {} was 0".format( datetime.now(), user[0], user[1]))
def unregistered_user_reminder(day_difference, dm_text): """ Check for unregistered users day_difference away from the current day and send a DM with the provided dm_text """ db_call = ("SELECT user_id, system " "FROM users " "WHERE register = 0 " "AND DATE(created_ts) BETWEEN DATE_SUB(NOW(), INTERVAL {} DAY) " "AND DATE_SUB(NOW(), INTERVAL {} DAY)").format(day_difference, (day_difference - 1)) try: unregistered_users = get_db_data(db_call) except Exception as e: logging.info(e) raise e logging.info("unregistered_users: {}".format(unregistered_users)) for user in unregistered_users: try: send_dm(user[0], dm_text, user[1]) logging.info("{}: User {} reminded after {} days.".format(str(datetime.now()), user[0], day_difference)) except tweepy.TweepError as e: logging.info("{}: Tweepy Error: {}".format(datetime.now(), e)) except Exception as e: logging.info("{}: Exception: {}".format(datetime.now(), e)) raise e
def calculate_donation_amount(amount, sender_id, system): donation_call = ("SELECT donation_percent FROM donation_info " "WHERE user_id = {} AND system = '{}'").format( sender_id, system) logging.info("{}: donation amount check call: {}".format( datetime.now(), donation_call)) donation_raw = get_db_data(donation_call) donation_percent = Decimal(str(donation_raw[0][0] * .01)) if amount * donation_percent >= float(MIN_TIP): donation = amount * donation_percent if CURRENCY == 'banano': donation = round(donation) else: donation = round(donation, 5) amount -= donation donation_amount = int(donation * CONVERT_MULTIPLIER[CURRENCY]) send_amount = int(amount * CONVERT_MULTIPLIER[CURRENCY]) else: donation = 0 donation_amount = 0 send_amount = int(amount * CONVERT_MULTIPLIER[CURRENCY]) return donation_amount, send_amount
def send_returned_notice_to_senders(): """ Notify all users who sent tips which were returned that their balance has been updated. """ sender_return_notice_call = ( "SELECT tip_list.sender_id, tip_list.system, sum(tip_list.amount) " "FROM tip_list " "INNER JOIN users " "ON tip_list.receiver_id = users.user_id AND tip_list.system = users.system " "WHERE DATE(tip_list.timestamp) < DATE_SUB(now(), interval 30 day) " "AND users.register = 0 " "AND tip_list.processed = 8 " "GROUP BY tip_list.sender_id, tip_list.system;") sender_return_list = get_db_data(sender_return_notice_call) sender_return_names = ( "SELECT tip_list.sender_id, tip_list.system, users.user_name " "FROM tip_list " "INNER JOIN users " "ON tip_list.receiver_id = users.user_id AND tip_list.system = users.system " "WHERE DATE(tip_list.timestamp) < DATE_SUB(now(), interval 30 day) " "AND users.register = 0 " "AND tip_list.processed = 8;") sender_return_name_list = get_db_data(sender_return_names) return_dict = {} for sender in sender_return_name_list: sender_comp = str(sender[0]) + "-" + str(sender[1]) if sender_comp not in return_dict.keys(): return_dict[sender_comp] = [sender[2]] else: return_dict[sender_comp].append(sender[2]) # for sender in sender_return_list: # donation_amount, send_amount = calculate_donation_amount(sender[2], sender[0], sender[1]) # sender_comp = str(sender[0]) + "-" + str(sender[1]) # logging.info("send amount in Nano = {}".format(Decimal(str(send_amount / CONVERT_MULTIPLIER[CURRENCY])))) # send_dm(sender[0], "You've had tips returned to your account due to the following list of users " # "not registering: {}. Your account has been credited {} {}. Continue spreading the " # "love or withdraw to your wallet!".format(return_dict[sender_comp], # Decimal(str(send_amount / CONVERT_MULTIPLIER[CURRENCY])), # CURRENCY.upper()), # sender[1]) mark_notified("senders")
def send_returned_notice_to_senders(): """ Notify all users who sent tips which were returned that their balance has been updated. """ sender_return_notice_call = ("SELECT tip_bot.tip_list.sender_id, tip_bot.tip_list.system, sum(tip_bot.tip_list.amount) " "FROM tip_bot.tip_list " "INNER JOIN tip_bot.users " "ON tip_bot.tip_list.receiver_id = tip_bot.users.user_id " "WHERE DATE(tip_bot.tip_list.timestamp) < DATE_SUB(now(), interval 30 day) " "AND tip_bot.users.register = 0 " "AND tip_bot.tip_list.processed = 8 " "GROUP BY tip_bot.tip_list.sender_id, tip_bot.tip_list.system;") sender_return_list = get_db_data(sender_return_notice_call) sender_return_names = ("SELECT tip_bot.tip_list.sender_id, tip_bot.tip_list.system, tip_bot.users.user_name " "FROM tip_bot.tip_list " "INNER JOIN tip_bot.users " "ON tip_bot.tip_list.receiver_id = tip_bot.users.user_id " "WHERE DATE(tip_bot.tip_list.timestamp) < DATE_SUB(now(), interval 30 day) " "AND tip_bot.users.register = 0 " "AND tip_bot.tip_list.processed = 8;") sender_return_name_list = get_db_data(sender_return_names) return_dict = {} for sender in sender_return_name_list: sender_comp = str(sender[0]) + "-" + str(sender[1]) if sender_comp not in return_dict.keys(): return_dict[sender_comp] = [sender[2]] else: return_dict[sender_comp].append(sender[2]) for sender in sender_return_list: sender_comp = str(sender[0]) + "-" + str(sender[1]) logging.info("sender return list = {}".format(return_dict[sender_comp])) send_dm(sender[0], "You've had tips returned to your account due to the following list of users " "not registering: {}. Your account has been credited {} NANO. Continue spreading the " "love or withdraw to your wallet!".format(return_dict[sender_comp], sender[2]), sender[1]) mark_notified("senders")
def check_telegram_member(chat_id, chat_name, member_id, member_name): check_user_call = ( "SELECT member_id, member_name FROM telegram_chat_members " "WHERE chat_id = {} and member_name = '{}'".format( chat_id, member_name)) user_check_data = get_db_data(check_user_call) logging.info("checking if user exists") if not user_check_data: logging.info("{}: User {}-{} not found in DB, inserting".format( datetime.now(), chat_id, member_name)) new_chat_member_call = ( "INSERT INTO telegram_chat_members (chat_id, chat_name, member_id, member_name) " "VALUES ({}, '{}', {}, '{}')".format(chat_id, chat_name, member_id, member_name)) set_db_data(new_chat_member_call) return
def send_returned_notice_to_receivers(): """ Notify all unregistered users that their tips are being returned. """ unregistered_users_call = ("SELECT DISTINCT tip_bot.tip_list.receiver_id, tip_bot.tip_list.system FROM tip_bot.tip_list " "INNER JOIN tip_bot.users " "ON tip_bot.tip_list.receiver_id = tip_bot.users.user_id " "WHERE DATE(tip_bot.tip_list.timestamp) < DATE_SUB(now(), interval 30 day) " "AND tip_bot.users.register = 0 " "AND tip_bot.tip_list.processed = 9;") unregistered_users_data = get_db_data(unregistered_users_call) for user in unregistered_users_data: send_dm(user[0], "You had tips that were sent 30 or more days ago, and you haven't registered your account. " "These tips were returned to the sender so they can continue to spread Nano to others. " "If you would like to keep any future tips, please register to prevent any more returns!", user[1]) mark_notified("receivers")
def send_returned_notice_to_senders(): """ Notify all users who sent tips which were returned that their balance has been updated. """ sender_return_notice_call = ("SELECT tip_bot.tip_list.sender_id, tip_bot.tip_list.system, sum(tip_bot.tip_list.amount) " "FROM tip_bot.tip_list " "INNER JOIN tip_bot.users " "ON tip_bot.tip_list.receiver_id = tip_bot.users.user_id " "WHERE DATE(tip_bot.tip_list.timestamp) < DATE_SUB(now(), interval 1 month) " "AND tip_bot.users.register = 0 " "AND tip_bot.tip_list.processed = 8 " "GROUP BY tip_bot.tip_list.sender_id, tip_bot.tip_list.system;") sender_return_list = get_db_data(sender_return_notice_call) for sender in sender_return_list: send_dm(sender[0], "You've had tips returned to your account due to unregistered users. Your account has been " "credited {} NANO. Continue spreading the love or withdraw to your wallet!".format(sender[2]), sender[1]) mark_notified("senders")
def mark_notified(user_type): """ Set the DB to show that the receivers were identified. """ if user_type == 'receivers': processed_num = 9 else: processed_num = 8 notified_users_call = ("SELECT dm_id " "FROM tip_bot.tip_list " "WHERE processed = {}".format(processed_num)) notified_users = get_db_data(notified_users_call) for id in notified_users: notified_send_call = ("UPDATE tip_bot.tip_list " "SET processed = %s " "WHERE dm_id = %s") notified_send_values = [(processed_num - 1), id[0]] set_db_data(notified_send_call, notified_send_values)
def validate_sender(message): """ Validate that the sender has an account with the tip bot, and has enough NANO to cover the tip. """ logging.info("{}: validating sender".format(datetime.now())) logging.info("sender id: {}".format(message['sender_id'])) logging.info("system: {}".format(message['system'])) db_call = "SELECT account, register FROM users where user_id = {} AND system = '{}'".format( message['sender_id'], message['system']) sender_account_info = get_db_data(db_call) if not sender_account_info: no_account_text = ( "You do not have an account with the bot. Please send a DM to me with !register to set up " "an account.") send_reply(message, no_account_text) logging.info("{}: User tried to send a tip without an account.".format( datetime.now())) message['sender_account'] = None return message message['sender_account'] = sender_account_info[0][0] message['sender_register'] = sender_account_info[0][1] if message['sender_register'] != 1: db_call = "UPDATE users SET register = 1 WHERE user_id = {} AND system = '{}'".format( message['sender_id'], message['system']) set_db_data(db_call) receive_pending(message['sender_account']) message['sender_balance_raw'] = rpc.account_balance( account='{}'.format(message['sender_account'])) message['sender_balance'] = message['sender_balance_raw'][ 'balance'] / 1000000000000000000000000000000 return message
def set_tip_list(message, users_to_tip): """ Loop through the message starting after the tip amount and identify any users that were tagged for a tip. Add the user object to the users_to_tip dict to process the tips. """ logging.info("{}: in set_tip_list.".format(datetime.now())) if message['system'] == 'twitter': for t_index in range(message['starting_point'] + 1, len(message['text'])): if len(message['text'][t_index]) > 0 and ( str(message['text'][t_index][0]) == "@" and str(message['text'][t_index]).lower() != ("@" + str(message['sender_screen_name']).lower())): try: user_info = api.get_user(message['text'][t_index]) except tweepy.TweepError as e: logging.info( "{}: The user sent a !tip command with a mistyped user: {}" .format(datetime.now(), message['text'][t_index])) logging.info("{}: Tip List Tweep error: {}".format( datetime.now(), e)) users_to_tip.clear() return message, users_to_tip user_dict = { 'receiver_id': user_info.id, 'receiver_screen_name': user_info.screen_name, 'receiver_account': None, 'receiver_register': None } users_to_tip.append(user_dict) logging.info("{}: Users_to_tip: {}".format( datetime.now(), users_to_tip)) if message['system'] == 'telegram': logging.info("trying to set tiplist in telegram: {}".format(message)) for t_index in range(message['starting_point'] + 1, len(message['text'])): if len(message['text'][t_index]) > 0: if str(message['text'][t_index][0]) == "@" and str( message['text'][t_index]).lower() != ( "@" + str(message['sender_screen_name']).lower()): check_user_call = ( "SELECT member_id, member_name FROM telegram_chat_members " "WHERE chat_id = {} and member_name = '{}'".format( message['chat_id'], message['text'][t_index][1:])) user_check_data = get_db_data(check_user_call) if user_check_data: receiver_id = user_check_data[0][0] receiver_screen_name = user_check_data[0][1] user_dict = { 'receiver_id': receiver_id, 'receiver_screen_name': receiver_screen_name, 'receiver_account': None, 'receiver_register': None } users_to_tip.append(user_dict) else: logging.info( "User not found in DB: chat ID:{} - member name:{}" .format(message['chat_id'], message['text'][t_index][1:])) missing_user_message = ( "{} not found in our records. In order to tip them, they need to be a " "member of the channel. If they are in the channel, please have them " "send a message in the chat so I can add them.". format(message['text'][t_index])) send_reply(message, missing_user_message) users_to_tip.clear() return message, users_to_tip logging.info("{}: Users_to_tip: {}".format(datetime.now(), users_to_tip)) message['total_tip_amount'] = message['tip_amount'] if len(users_to_tip) > 0 and message['tip_amount'] != -1: message['total_tip_amount'] *= len(users_to_tip) return message, users_to_tip
def return_tips(): tips_to_return_call = ("SELECT tip_list.dm_id, tip_list.sender_id, " "users.account, tip_list.amount, tip_list.system " "FROM tip_list " "INNER JOIN users " "ON tip_list.receiver_id = users.user_id AND tip_list.system = users.system " "WHERE DATE(tip_list.timestamp) < DATE_SUB(now(), interval 30 day) " "AND users.register = 0 " "AND tip_list.processed = 2;") tip_list = get_db_data(tips_to_return_call) for tip in tip_list: transaction_id = tip[0] sender_id = tip[1] receiver_account = tip[2] amount = Decimal(str(tip[3])) system = tip[4] logging.info("{}: Returning tip {}".format(datetime.now(), transaction_id)) sender_account_call = "SELECT account FROM users WHERE user_id = {} AND system = '{}'".format(sender_id, system) sender_account_info = get_db_data(sender_account_call) sender_account = sender_account_info[0][0] donation_amount, send_amount = calculate_donation_amount(amount, sender_id, system) logging.info("donation amount: {}".format(donation_amount)) logging.info("send_amount: {} - {}".format(amount, send_amount)) receive_pending(receiver_account) work = get_pow(receiver_account) try: if work == '': send_hash = rpc.send(wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(sender_account), amount=send_amount) if donation_amount > 0: donation_hash = rpc.send(wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(BOT_ACCOUNT), amount=donation_amount) logging.info("{}: Donation sent from account {} under hash: {}".format(datetime.now(), receiver_account, donation_hash)) else: send_hash = rpc.send(wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(sender_account), amount=send_amount, work=work) if donation_amount > 0: donation_work = get_pow(receiver_account) donation_hash = rpc.send(wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(BOT_ACCOUNT), amount=donation_amount, work=donation_work) logging.info("{}: Donation sent from account {} under hash: {}".format(datetime.now(), receiver_account, donation_hash)) logging.info("{}: Tip returned under hash: {}".format(str(datetime.now()), send_hash)) except nano.rpc.RPCException as e: logging.info("{}: Insufficient balance to return {} raw and {} donation from account {}. Descriptive error: {}".format(datetime.now(), send_amount, donation_amount, receiver_account, e)) insufficient_balance_check = rpc.account_balance(receiver_account) logging.info("Current balance: {}".format(insufficient_balance_check)) insufficient_balance_call = ("UPDATE tip_list " "SET processed = 6 " "WHERE dm_id = %s;") insufficient_balance_values = [transaction_id,] set_db_data(insufficient_balance_call, insufficient_balance_values) continue except Exception as f: logging.info("{}: Unexpected error: {}".format(datetime.now(), f)) continue update_tip_call = ("UPDATE tip_list " "SET processed = 9 " "WHERE dm_id = %s;") update_tip_values = [transaction_id,] try: set_db_data(update_tip_call, update_tip_values) except Exception as e: logging.info("{}: Error updating tip to returned: {}".format(datetime.now(), e)) send_returned_notice_to_receivers() send_returned_notice_to_senders()
balance = rpc.account_balance(account=send_account) if balance['balance'] > 0: work = modules.currency.get_pow(send_account) block = rpc.send(wallet=BB_WALLET, source=send_account, destination=receive_account, amount=balance['balance'], work=work) return block return '' # get all user IDs, usernames accounts and registration status from bbedward bbedward_users = db.get_db_data( "SELECT user_id, user_name, account, register FROM bbedward.users;") # get all user IDs from bananotipbot new_users = db.get_db_data( "SELECT user_id, system, account FROM banano_tip_bot.users WHERE system = 'telegram';" ) user_ids = [] for user in new_users: user_ids.append(user[0]) # for each record from bbedward, check if it exists in bananotipbot for user in bbedward_users: if user[0] not in user_ids: print("user: {}".format(user)) print("generating a new account")
def return_tips(): tips_to_return_call = ( "SELECT tip_list.dm_id, tip_list.amount, users.account, tip_list.sender_id, tip_list.system " "FROM tip_bot.tip_list " "INNER JOIN users ON tip_list.receiver_id = users.user_id AND tip_list.system = users.system " "WHERE processed = 6;") tip_list = get_db_data(tips_to_return_call) for tip in tip_list: transaction_id = tip[0] sender_id = tip[3] receiver_account = tip[2] amount = Decimal(str(tip[1])) system = tip[4] logging.info("{}: Returning tip {}".format(datetime.now(), transaction_id)) donation_amount, send_amount = calculate_donation_amount( amount, sender_id, system) logging.info("donation amount: {}".format(donation_amount)) logging.info("send_amount: {} - {}".format(amount, send_amount)) receive_pending(receiver_account) work = get_pow(receiver_account) try: if work == '': if donation_amount > 0: donation_hash = rpc.send( wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(BOT_ACCOUNT), amount=donation_amount) logging.info( "{}: Donation sent from account {} under hash: {}". format(datetime.now(), receiver_account, donation_hash)) else: if donation_amount > 0: donation_hash = rpc.send( wallet="{}".format(WALLET), source="{}".format(receiver_account), destination="{}".format(BOT_ACCOUNT), amount="{}".format(donation_amount), work=work) logging.info( "{}: Donation sent from account {} under hash: {}". format(datetime.now(), receiver_account, donation_hash)) except nano.rpc.RPCException as e: logging.info( "{}: Insufficient balance to return {} raw and {} donation from account {}. Descriptive error: {}" .format(datetime.now(), send_amount, donation_amount, receiver_account, e)) insufficient_balance_check = rpc.account_balance(receiver_account) logging.info( "Current balance: {}".format(insufficient_balance_check)) if int(insufficient_balance_check['balance']) == 0: insufficient_balance_call = ("UPDATE tip_list " "SET processed = 9 " "WHERE dm_id = %s;") else: insufficient_balance_call = ("UPDATE tip_list " "SET processed = 6 " "WHERE dm_id = %s;") insufficient_balance_values = [ transaction_id, ] set_db_data(insufficient_balance_call, insufficient_balance_values) continue except Exception as f: logging.info("{}: Unexpected error: {}".format(datetime.now(), f)) continue update_tip_call = ("UPDATE tip_list " "SET processed = 9 " "WHERE dm_id = %s;") update_tip_values = [ transaction_id, ] try: set_db_data(update_tip_call, update_tip_values) except Exception as e: logging.info("{}: Error updating tip to returned: {}".format( datetime.now(), e))