Exemplo n.º 1
0
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
Exemplo n.º 2
0
def register_process(message):
    import modules.db as db
    import modules.social as social
    """
    When the user sends .register, create an account for them and mark it registered.  If they already have an account
    reply with their account number.
    """
    logging.info("{}: In register process.".format(datetime.datetime.utcnow()))
    try:
        user = db.User.select().where(db.User.user_id == int(message['sender_id'])).get()
        if user.register == 0:
            # The user has an account, but needed to register, so send a message to the user with their account
            sender_account = user.account
            db.User.update(register=1).where(
                (db.User.user_id == int(message['sender_id'])) &
                (db.User.register == 0)).execute()

            account_registration_text = "You have successfully registered for an account.  Your deposit address is:"
            social.send_account_message(account_registration_text, message,
                                        sender_account)

            logging.info(
                "{}: User has an account, but needed to register.  Message sent".
                format(datetime.datetime.utcnow()))
        else:
            # The user had an account and already registered, so let them know their account.
            sender_account = user.account
            account_already_registered = "You already have registered your account.  Your deposit address is:"
            social.send_account_message(account_already_registered, message,
                                        sender_account)

            logging.info(
                "{}: User has a registered account.  Message sent.".format(
                    datetime.datetime.utcnow()))
    except db.User.DoesNotExist:
        # Create an account for the user
        sender_account = rpc.account_create(
            wallet="{}".format(WALLET), work=False)
        user = db.User(
            user_id = int(message['sender_id']),
            user_name = message['sender_screen_name'],
            account = sender_account,
            register=1,
            created_ts=datetime.datetime.utcnow()
        )
        if user.save(force_insert=True) > 0:
            account_text = "You have successfully registered for an account.  Your deposit address is:"
            social.send_account_message(account_text, message, sender_account)
        else:
            account_text = "Something went wrong - please try again later ot inform one of my masters"
            social.send_dm(message['sender_id'], account_text)

        logging.info("{}: Register successful!".format(datetime.datetime.utcnow()))
Exemplo n.º 3
0
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")
Exemplo n.º 4
0
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")
Exemplo n.º 5
0
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")
Exemplo n.º 6
0
def help_process(message):
    import modules.social as social
    """
    Reply to the sender with help commands
    """
    help_message = (
        "Thank you for using my services @BANANOTipBot!  Below is a list of commands, and a description of how you can interact with me:\n\n"
        + BULLET +
        " .help: The BANANOTipBot 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\n\n"
        + BULLET +
        " .register: Creates a fresh BANANO account address specifically for you.  This is used to store your tips. Make sure to withdraw to a private wallet such as Kalium or BananoVault, as the tip bot is not meant to be a long term storage device for BANANO.\n\n"
        + BULLET +
        " .balance: This shows you how much funds are in your your account.\n\n"
        + BULLET +
        " .tip: Tips are sent directly to @username on telegram.  Tag @BANANOTipBot and mention .tip <amount> <@username>.  EXAMPLE: .tip 1 @user will send a 1 BANANO tip to @user.\n\n"
        + BULLET +
        " .account: Returns the account number.  You can use this to deposit more BANANO to tip from your personal wallet.\n\n"
        + BULLET +
        " .withdraw: Proper usage is .withdraw ban_1meme1...  This will send the full balance of your tip account to another external BANANO account.  Optional: You can include an amount to withdraw by sending .withdraw <amount> <address>.  Example: .withdraw 1 ban_1meme1... would withdraw 1 BAN to account ban_1meme1...\n\n"
    )
    social.send_dm(message['sender_id'], help_message)
    logging.info("{}: Help message sent!".format(datetime.datetime.utcnow()))
Exemplo n.º 7
0
def balance_process(message):
    import modules.db as db
    import modules.currency as currency
    import modules.social as social
    """
    When the user sends a DM containing !balance, reply with the balance of the account linked with their Twitter ID
    """
    logging.info("{}: In balance process".format(datetime.datetime.utcnow()))
    try:
        user = db.User.select().where(db.User.user_id == int(message['sender_id'])).get()
        message['sender_account'] = user.account
        sender_register = user.register

        if sender_register == 0:
            db.User.update(register=1).where(
                (db.User.user_id == int(message['sender_id'])) &
                (db.User.register == 0)).execute()

        currency.receive_pending(message['sender_account'])
        balance_return = rpc.account_balance(
            account="{}".format(message['sender_account']))
        message['sender_balance_raw'] = balance_return['balance']
        message['sender_balance'] = BananoConversions.raw_to_banano(balance_return['balance'])

        balance_text = "Your balance is {} BAN.".format(
            message['sender_balance'])
        social.send_dm(message['sender_id'], balance_text)
        logging.info("{}: Balance Message Sent!".format(datetime.datetime.utcnow()))
    except db.User.DoesNotExist:
        logging.info(
            "{}: User tried to check balance without an account".format(
                datetime.datetime.utcnow()))
        balance_message = (
            "There is no account linked to your username.  Please respond with .register to "
            "create an account.")
        social.send_dm(message['sender_id'], balance_message)
Exemplo n.º 8
0
def withdraw_process(message):
    import modules.db as db
    import modules.currency as currency
    import modules.social as social
    """
    When the user sends !withdraw, send their entire balance to the provided account.  If there is no provided account
    reply with an error.
    """
    logging.info('{}: in withdraw process.'.format(datetime.datetime.utcnow()))
    # check if there is a 2nd argument
    if 3 >= len(message['dm_array']) >= 2:
        # if there is, retrieve the sender's account and wallet
        try:
            user = db.User.select().where(db.User.user_id == int(message['sender_id'])).get()
            sender_account = user.account
            currency.receive_pending(sender_account)
            balance_return = rpc.account_balance(
                account='{}'.format(sender_account))

            if len(message['dm_array']) == 2:
                receiver_account = message['dm_array'][1].lower()
            else:
                receiver_account = message['dm_array'][2].lower()

            if rpc.validate_account_number(receiver_account) == 0:
                invalid_account_text = (
                    "The account address you provided is invalid.  Please double check and "
                    "resend your request.")
                social.send_dm(message['sender_id'], invalid_account_text)
                logging.info(
                    "{}: The BAN account address is invalid: {}".format(
                        datetime.datetime.utcnow(), receiver_account))
            elif balance_return['balance'] == 0:
                no_balance_text = (
                    "You have 0 balance in your account.  Please deposit to your address {} to "
                    "send more tips!".format(sender_account))
                social.send_dm(message['sender_id'], no_balance_text)
                logging.info(
                    "{}: The user tried to withdraw with 0 balance".format(
                        datetime.datetime.utcnow()))
            else:
                if len(message['dm_array']) == 3:
                    try:
                        withdraw_amount = Decimal(message['dm_array'][1])
                    except Exception as e:
                        logging.info("{}: withdraw no number ERROR: {}".format(
                            datetime.datetime.utcnow(), e))
                        invalid_amount_text = (
                            "You did not send a number to withdraw.  Please resend with the format"
                            ".withdraw <account> or !withdraw <amount> <account>"
                        )
                        social.send_dm(message['sender_id'],
                                       invalid_amount_text)
                        return
                    withdraw_amount_raw = BananoConversions.banano_to_raw(withdraw_amount)
                    if Decimal(withdraw_amount_raw) > Decimal(
                            balance_return['balance']):
                        not_enough_balance_text = (
                            "You do not have that much BAN in your account.  To withdraw your "
                            "full amount, send .withdraw <account>")
                        social.send_dm(message['sender_id'],
                                       not_enough_balance_text)
                        return
                else:
                    withdraw_amount_raw = balance_return['balance']
                    withdraw_amount = BananoConversions.raw_to_banano(balance_return[
                        'balance'])
                # send the total balance to the provided account
                work = currency.get_pow(sender_account)
                if work == '':
                    logging.info("{}: processed without work".format(
                        datetime.datetime.utcnow()))
                    send_hash = rpc.send(
                        wallet="{}".format(WALLET),
                        source="{}".format(sender_account),
                        destination="{}".format(receiver_account),
                        amount=withdraw_amount_raw)
                else:
                    logging.info("{}: processed with work: {}".format(
                        datetime.datetime.utcnow(), work))
                    send_hash = rpc.send(
                        wallet="{}".format(WALLET),
                        source="{}".format(sender_account),
                        destination="{}".format(receiver_account),
                        amount=withdraw_amount_raw,
                        work=work)
                logging.info("{}: send_hash = {}".format(
                    datetime.datetime.utcnow(), send_hash))
                # respond that the withdraw has been processed
                withdraw_text = ("You have successfully withdrawn {} BANANO!".
                                 format(withdraw_amount))
                social.send_dm(message['sender_id'], withdraw_text)
                logging.info("{}: Withdraw processed.  Hash: {}".format(
                    datetime.datetime.utcnow(), send_hash))
        except db.User.DoesNotExist:
            withdraw_no_account_text = "You do not have an account.  Respond with .register to set one up."
            social.send_dm(message['sender_id'], withdraw_no_account_text)
            logging.info("{}: User tried to withdraw with no account".format(
                datetime.datetime.utcnow()))
    else:
        incorrect_withdraw_text = (
            "I didn't understand your withdraw request.  Please resend with .withdraw "
            "<optional:amount> <account>.  Example, .withdraw 1 ban_1meme1... would "
            "withdraw 1 BANANO to account ban_1meme1...  Also, .withdraw "
            "ban_1meme1... would withdraw your entire balance to account "
            "ban_1meme1...")
        social.send_dm(message['sender_id'], incorrect_withdraw_text)
        logging.info("{}: User sent a withdraw with invalid syntax.".format(
            datetime.datetime.utcnow()))
Exemplo n.º 9
0
def parse_action(message):
    import modules.social as social
    if message['dm_action'] == '.help' or message[
            'dm_action'] == '/help' or message['dm_action'] == '/start':
        try:
            help_process(message)
        except Exception as e:
            logging.info("Exception: {}".format(e))
            raise e
        finally:
            return '', HTTPStatus.OK

    elif message['dm_action'] == '.balance' or message[
            'dm_action'] == '/balance':
        try:
            balance_process(message)
        except Exception as e:
            logging.info("Exception: {}".format(e))
            raise e
        finally:
            return '', HTTPStatus.OK

    elif message['dm_action'] == '.register' or message[
            'dm_action'] == '/register':
        try:
            register_process(message)
        except Exception as e:
            logging.info("Exception: {}".format(e))
            raise e
        finally:
            return '', HTTPStatus.OK

    elif message['dm_action'] == '.tip' or message['dm_action'] == '/ban':
        try:
            redirect_tip_text = (
                "Tips are processed through public messages now.  Please send this message in group chat in the format "
                ".tip 1 @user1.")
            social.send_dm(message['sender_id'], redirect_tip_text)
        except Exception as e:
            logging.info("Exception: {}".format(e))
            raise e
        finally:
            return '', HTTPStatus.OK

    elif message['dm_action'] == '.withdraw' or message[
            'dm_action'] == '/withdraw':
        try:
            withdraw_process(message)
        except Exception as e:
            logging.info("Exception: {}".format(e))
            raise e
        finally:
            return '', HTTPStatus.OK

    elif message['dm_action'] == '.account' or message[
            'dm_action'] == '/account':
        try:
            account_process(message)
        except Exception as e:
            logging.info("Exception: {}".format(e))
            raise e
        finally:
            return '', HTTPStatus.OK

    else:
        try:
            wrong_format_text = (
                "The command or syntax you sent is not recognized.  Please send .help for a list "
                "of commands and what they do.")
            social.send_dm(message['sender_id'], wrong_format_text)
            logging.info('unrecognized syntax')
        except Exception as e:
            logging.info("Exception: {}".format(e))
            raise e
        finally:
            return '', HTTPStatus.OK

    return '', HTTPStatus.OK
Exemplo n.º 10
0
def send_tip(message, users_to_tip, tip_index):
    import modules.db as db
    import modules.social as social
    """
    Process tip for specified user
    """
    logging.info("{}: sending tip to {}".format(
        datetime.datetime.utcnow(), users_to_tip[tip_index]['receiver_screen_name']))
    if str(users_to_tip[tip_index]['receiver_id']) == str(
            message['sender_id']):
        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)

        logging.info("{}: User tried to tip themself").format(datetime.datetime.utcnow())
        return

    # Check if the receiver has an account
    try:
        user = db.User.select().where(db.User.user_id == 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)
        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'],
            register=0,
            created_ts=datetime.datetime.utcnow()
        )
        user.save(force_insert=True)
        logging.info(
            "{}: Sender sent to a new receiving account.  Created  account {}".
            format(datetime.datetime.utcnow(),
                   users_to_tip[tip_index]['receiver_account']))
    # Send the tip

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

    work = get_pow(message['sender_account'])
    logging.info("Sending Tip:")
    logging.info("From: {}".format(message['sender_account']))
    logging.info("To: {}".format(users_to_tip[tip_index]['receiver_account']))
    logging.info("amount: {:f}".format(message['tip_amount_raw']))
    logging.info("id: {}".format(message['tip_id']))
    logging.info("work: {}".format(work))
    if work == '':
        message['send_hash'] = rpc.send(
            wallet="{}".format(WALLET),
            source="{}".format(message['sender_account']),
            destination="{}".format(
                users_to_tip[tip_index]['receiver_account']),
            amount="{}".format(int(message['tip_amount_raw'])),
            id="tip-{}".format(message['tip_id']))
    else:
        message['send_hash'] = rpc.send(
            wallet="{}".format(WALLET),
            source="{}".format(message['sender_account']),
            destination="{}".format(
                users_to_tip[tip_index]['receiver_account']),
            amount="{}".format(int(message['tip_amount_raw'])),
            work=work,
            id="tip-{}".format(message['tip_id']))
    # Update the DB
    db.set_db_data_tip(message, users_to_tip, tip_index)

    # Get receiver's new balance
    try:
        logging.info("{}: Checking to receive new tip")
        receive_pending(users_to_tip[tip_index]['receiver_account'])
        balance_return = rpc.account_balance(
            account="{}".format(users_to_tip[tip_index]['receiver_account']))
        users_to_tip[tip_index][
            'balance'] = BananoConversions.raw_to_banano(balance_return['balance'])

        # create a string to remove scientific notation from small decimal tips
        if str(users_to_tip[tip_index]['balance'])[0] == ".":
            users_to_tip[tip_index]['balance'] = "0{}".format(
                str(users_to_tip[tip_index]['balance']))
        else:
            users_to_tip[tip_index]['balance'] = str(
                users_to_tip[tip_index]['balance'])

        # Send a DM to the receiver
        receiver_tip_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 https://banano.cc"
            .format(message['sender_screen_name'], message['tip_amount_text'])) 
        social.send_dm(users_to_tip[tip_index]['receiver_id'],
                       receiver_tip_text)
    except Exception as e:
        logging.info(
            "{}: ERROR IN RECEIVING NEW TIP - POSSIBLE NEW ACCOUNT NOT REGISTERED WITH DPOW: {}"
            .format(datetime.datetime.utcnow(), e))

    logging.info("{}: tip sent to {} via hash {}".format(
        datetime.datetime.utcnow(), users_to_tip[tip_index]['receiver_screen_name'],
        message['send_hash']))