コード例 #1
0
def handle_balance(message):
    username = str(message.author)
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    add_history_record(
        username=str(message.author),
        comment_or_message="message",
        reddit_time=message_time,
        action="balance",
        comment_id=message.name,
        comment_text=str(message.body)[:255],
    )
    try:
        acct = Account.get(username=username)
        results = check_balance(acct.address)

        response = text.BALANCE % (
            acct.address,
            from_raw(results),
            acct.address,
        )

        return response
    except Account.DoesNotExist:
        return text.NOT_OPEN
コード例 #2
0
def handle_balance(message):
    username = str(message.author)
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    add_history_record(
        username=str(message.author),
        comment_or_message="message",
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
        action="balance",
        comment_id=message.name,
        comment_text=str(message.body)[:255],
    )
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        results = check_balance(result[0][0])

        response = text.BALANCE % (
            result[0][0],
            from_raw(results[0]),
            from_raw(results[1]),
            result[0][0],
        )

        return response
    return text.NOT_OPEN
コード例 #3
0
def handle_balance(message):
    username = str(message.author)
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    add_history_record(
        username=str(message.author),
        comment_or_message="message",
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
        action="balance",
        comment_id=message.name,
        comment_text=str(message.body)[:255],
    )
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        results = check_balance(result[0][0])

        response = (
            "At address %s:\n\nAvailable: %s Nano\n\nUnpocketed: %s Nano\n\nNano "
            "will be pocketed automatically unless the transaction is below "
            "0.0001 Nano."
            "\n\nhttps://nanocrawler.cc/explorer/account/%s" %
            (result[0][0], results[0] / 10**30, results[1] / 10**30,
             result[0][0]))

        return response
    return "You do not have an open account yet"
コード例 #4
0
def handle_projects(message):
    """
    Handles creation and updates of crowdfunding (NanoCenter) projects
    """
    parsed_text = parse_text(str(message.body))
    response = text.CROWD_FUNDING["projects"]
    if (str(message.author).lower()
            in DONATION_ADMINS + TIPBOT_OWNER) and len(parsed_text) > 2:
        sql = "INSERT INTO projects (project, address) VALUES(%s, %s) ON DUPLICATE KEY UPDATE address=%s"
        val = (parsed_text[1], parsed_text[2], parsed_text[2])
        MYCURSOR.execute(sql, val)
        MYDB.commit()
    add_history_record(
        username=str(message.author),
        action="project",
        comment_text=str(message.body)[:255],
        comment_or_message="message",
        comment_id=message.name,
    )

    sql = "SELECT project, address FROM projects"
    MYCURSOR.execute(sql)
    results = MYCURSOR.fetchall()
    for result in results:
        response += "%s %s  \n" % (result[0], result[1])
    return response
コード例 #5
0
def handle_create(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    add_history_record(
        username=str(message.author),
        comment_or_message="message",
        reddit_time=message_time,
        action="create",
        comment_id=message.name,
        comment_text=str(message.body)[:255],
    )

    username = str(message.author)
    try:
        acct = Account.get(username=username)
        response = text.ALREADY_EXISTS % (acct.address, acct.address)
    except Account.DoesNotExist:
        address = tipper_functions.add_new_account(username)['address']
        if address is None:
            response = text.ACCOUNT_MAKE_ERROR_ERROR
        else:
            response = WELCOME_CREATE % (address, address)
        # reddit.redditor(message_recipient).message(subject, message_text)

    return response
コード例 #6
0
def handle_silence(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    username = str(message.author)
    add_history_record(
        username=str(message.author),
        action="silence",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
    )

    parsed_text = parse_text(str(message.body))

    if len(parsed_text) < 2:
        response = text.SILENCE["parse_error"]
        return response

    if parsed_text[1] == "yes":
        sql = "UPDATE accounts SET silence = TRUE WHERE username = %s "
        val = (username, )
        MYCURSOR.execute(sql, val)
        response = text.SILENCE["yes"]
    elif parsed_text[1] == "no":
        sql = "UPDATE accounts SET silence = FALSE WHERE username = %s"
        val = (username, )
        MYCURSOR.execute(sql, val)
        response = text.SILENCE["no"]
    else:
        response = text.SILENCE["yes_no"]
    MYDB.commit()

    return response
コード例 #7
0
def handle_silence(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    username = str(message.author)
    add_history_record(
        username=str(message.author),
        action="silence",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=message_time,
    )

    parsed_text = parse_text(str(message.body))

    if len(parsed_text) < 2:
        response = text.SILENCE["parse_error"]
        return response

    if parsed_text[1] == "yes":
        Account.update(silence=True).where(
            Account.username == username).execute()
        response = text.SILENCE["yes"]
    elif parsed_text[1] == "no":
        Account.update(silence=False).where(
            Account.username == username).execute()
        response = text.SILENCE["no"]
    else:
        response = text.SILENCE["yes_no"]

    return response
コード例 #8
0
def handle_create(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    add_history_record(
        username=str(message.author),
        comment_or_message="message",
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
        action="create",
        comment_id=message.name,
        comment_text=str(message.body)[:255],
    )

    username = str(message.author)
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) is 0:
        address = tipper_functions.add_new_account(username)["address"]
        response = WELCOME_CREATE % (address, address)
        message_recipient = TIP_BOT_USERNAME
        subject = "send"
        message_text = "send 0.001 %s" % username
        sql = "INSERT INTO messages (username, subject, message) VALUES (%s, %s, %s)"
        val = (message_recipient, subject, message_text)
        MYCURSOR.execute(sql, val)
        MYDB.commit()

        # reddit.redditor(message_recipient).message(subject, message_text)

    else:
        response = text.ALREADY_EXISTS % (result[0][0], result[0][0])
    return response
コード例 #9
0
def handle_opt_in(message):
    add_history_record(
        username=str(message.author),
        action="opt-in",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=datetime.utcfromtimestamp(message.created_utc),
    )
    Account.update(opt_in=True).where(
        Account.username == str(message.author)).execute()
    response = text.OPT_IN
    return response
コード例 #10
0
def handle_help(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    add_history_record(
        username=str(message.author),
        action="help",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
    )
    response = HELP
    return response
コード例 #11
0
def handle_opt_in(message):
    add_history_record(
        username=str(message.author),
        action="opt-in",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=datetime.utcfromtimestamp(
            message.created_utc).strftime("%Y-%m-%d %H:%M:%S"),
    )
    sql = "UPDATE accounts SET opt_in = TRUE WHERE username = %s"
    MYCURSOR.execute(sql, (str(message.author), ))
    MYDB.commit()
    response = text.OPT_IN
    return response
コード例 #12
0
def handle_opt_in(message):
    add_history_record(
        username=str(message.author),
        action="opt-in",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=datetime.utcfromtimestamp(
            message.created_utc).strftime("%Y-%m-%d %H:%M:%S"),
    )
    sql = "UPDATE accounts SET opt_in = TRUE WHERE username = %s"
    MYCURSOR.execute(sql, (str(message.author), ))
    MYDB.commit()
    response = (
        "Welcome back! You have opted back in. Your account will be restored with the same address, "
        "though any Nano you had may have already been returned or donated already."
    )
    return response
コード例 #13
0
def handle_receive(message):
    """

    :param message:
    :return:
    """
    message_time = datetime.utcfromtimestamp(message.created_utc)
    username = str(message.author)
    # find any accounts associated with the redditor
    sql = "SELECT address, private_key FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        address = result[0][0]
        open_or_receive(address, result[0][1])
        balance = check_balance(address)
        add_history_record(
            username=username,
            action="receive",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            address=address,
            comment_id=message.name,
            comment_or_message="message",
        )
        response = (
            "At address %s, you currently have %s Nano available, and %s Nano "
            "unpocketed. If you have any unpocketed, create a new "
            "message containing the word "
            "'receive'\n\nhttps://nanocrawler.cc/explorer/account/%s" %
            (address, balance[0] / 10**30, balance[1] / 10**30, address))
        return response
    else:
        add_history_record(
            username=username,
            action="receive",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            comment_id=message.name,
            comment_or_message="message",
        )
        response = (
            "You do not currently have an account open. To create one, "
            "respond with the text 'create' in the message body.")
        return response
コード例 #14
0
def handle_opt_out(message):
    add_history_record(
        username=str(message.author),
        action="opt-out",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=datetime.utcfromtimestamp(
            message.created_utc).strftime("%Y-%m-%d %H:%M:%S"),
    )

    sql = "UPDATE accounts SET opt_in = FALSE WHERE username = %s"
    MYCURSOR.execute(sql, (str(message.author), ))
    MYDB.commit()

    response = (
        "You have opted-out and I promise not to bother you anymore.\n\nReturnable Nano will be returned "
        "to the tippers, and the remaining balance will be donated to the tipbot fund.\n\nIf this was in "
        "error, please respond immediately with the text `opt-in`.")
    return response
コード例 #15
0
def handle_receive(message):
    """

    :param message:
    :return:
    """
    message_time = datetime.utcfromtimestamp(message.created_utc)
    username = str(message.author)
    # find any accounts associated with the redditor
    sql = "SELECT address, private_key FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        address = result[0][0]
        open_or_receive(address, result[0][1])
        balance = check_balance(address)
        add_history_record(
            username=username,
            action="receive",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            address=address,
            comment_id=message.name,
            comment_or_message="message",
        )
        response = text.RECEIVE["balance"] % (
            address,
            from_raw(balance[0]),
            from_raw(balance[1]),
            address,
        )
        return response
    else:
        add_history_record(
            username=username,
            action="receive",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            comment_id=message.name,
            comment_or_message="message",
        )
        response = text.NOT_OPEN
        return response
コード例 #16
0
def handle_silence(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    username = str(message.author)
    add_history_record(
        username=str(message.author),
        action="silence",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
    )

    parsed_text = parse_text(str(message.body))

    if len(parsed_text) < 2:
        response = ("I couldn't parse your command. I was expecting 'silence "
                    "<yes/no>'. Be sure to check your spacing.")
        return response

    if parsed_text[1] == "yes":
        sql = "UPDATE accounts SET silence = TRUE WHERE username = %s "
        val = (username, )
        MYCURSOR.execute(sql, val)
        response = ("Silence set to 'yes'. You will no longer receive tip "
                    "notifications or be tagged by the bot.")
    elif parsed_text[1] == "no":
        sql = "UPDATE accounts SET silence = FALSE WHERE username = %s"
        val = (username, )
        MYCURSOR.execute(sql, val)
        response = (
            "Silence set to 'no'. You will receive tip notifications and be "
            "tagged by the bot in replies.")
    else:
        response = (
            "I did not see 'no' or 'yes' after 'silence'. If you did type "
            "that, check your spacing.")
    MYDB.commit()

    return response
コード例 #17
0
def handle_convert(message):
    """
    Returns the Nano amount of a currency.
    """
    parsed_text = parse_text(str(message.body))

    add_history_record(
        username=str(message.author),
        action="convert",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=datetime.utcfromtimestamp(
            message.created_utc).strftime("%Y-%m-%d %H:%M:%S"),
    )

    if len(parsed_text) < 2:
        return text.CONVERT["no_amount_specified"]
    try:
        amount = parse_raw_amount(parsed_text)
    except TipError:
        return text.SEND_TEXT[120] % parsed_text[1]
    return text.CONVERT["success"] % (parsed_text[1], from_raw(amount))
コード例 #18
0
def handle_create(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    add_history_record(
        username=str(message.author),
        comment_or_message="message",
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
        action="create",
        comment_id=message.name,
        comment_text=str(message.body)[:255],
    )

    username = str(message.author)
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) is 0:
        address = tipper_functions.add_new_account(username)
        response = WELCOME_CREATE % (address, address)
        message_recipient = TIP_BOT_USERNAME
        subject = "send"
        message_text = "send 0.001 %s" % username
        sql = "INSERT INTO messages (username, subject, message) VALUES (%s, %s, %s)"
        val = (message_recipient, subject, message_text)
        MYCURSOR.execute(sql, val)
        MYDB.commit()

        # reddit.redditor(message_recipient).message(subject, message_text)

    else:
        response = (
            "It looks like you already have an account. In any case it is now "
            "**active**. Your Nano address is %s."
            "\n\nhttps://nanocrawler.cc/explorer/account/%s" %
            (result[0][0], result[0][0]))
    return response
コード例 #19
0
def handle_send(message):
    """
    Extracts send command information from a PM command
    :param message:
    :return:
    """
    parsed_text = parse_text(str(message.body))
    username = str(message.author)
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    entry_id = add_history_record(
        username=username,
        action="send",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
        comment_text=str(message.body)[:255],
    )
    response = {"username": username}

    # check that there are enough fields (i.e. a username)
    if len(parsed_text) <= 2:
        update_history_notes(entry_id, "no recipient or amount specified")
        response["status"] = 110
        return response

    # check that it wasn't a mistyped currency code or something
    if parsed_text[2] in EXCLUDED_REDDITORS:
        response["status"] = 140
        return response

    # pull sender account info
    sender_info = tipper_functions.account_info(response["username"])
    if not sender_info:
        update_history_notes(entry_id, "user does not exist")
        response["status"] = 100
        return response

    # parse the amount
    try:
        response["amount"] = parse_raw_amount(parsed_text,
                                              response["username"])
    except TipError as err:
        response["status"] = 120
        response["amount"] = parsed_text[1]
        update_history_notes(entry_id, err.sql_text)
        return response

    # check if it's above the program minimum
    if response["amount"] < nano_to_raw(PROGRAM_MINIMUM):
        update_history_notes(entry_id, "amount below program limit")
        response["status"] = 130
        return response

    # check the user's balance
    if response["amount"] > sender_info["balance"]:
        update_history_notes(entry_id, "insufficient funds")
        response["status"] = 160
        return response

    recipient_text = parsed_text[2]

    # catch invalid redditor AND address
    try:
        recipient_info = parse_recipient_username(recipient_text)
    except TipError as err:
        update_history_notes(entry_id, err.sql_text)
        response["recipient"] = recipient_text
        response["status"] = 170
        return response

    # if we have a username, pull their info
    if "username" in recipient_info.keys():
        response["recipient"] = recipient_info["username"]
        recipient_name = recipient_info["username"]
        recipient_info = tipper_functions.account_info(recipient_name)
        response["status"] = 10
        if recipient_info is None:
            recipient_info = tipper_functions.add_new_account(
                response["recipient"])
            response["status"] = 20
        elif not recipient_info["opt_in"]:
            response["status"] = 190
            return response
    # check if it's an address
    else:
        # otherwise, just use the address. Everything is None except address
        recipient_info["minimum"] = 0
        response["recipient"] = recipient_info["address"]
        response["status"] = 30

    # check the send amount is above the user minimum, if a username is provided
    # if it was just an address, this would be -1
    if response["amount"] < recipient_info["minimum"]:
        update_history_notes(entry_id, "below user minimum")
        response["status"] = 180
        response["minimum"] = recipient_info["minimum"]
        return response

    response["hash"] = send(
        sender_info["address"],
        sender_info["private_key"],
        response["amount"],
        recipient_info["address"],
    )["hash"]
    # if it was an address, just send to the address
    if "username" not in recipient_info.keys():
        sql = (
            "UPDATE history SET notes = %s, address = %s, username = %s, recipient_username = %s, "
            "recipient_address = %s, amount = %s, return_status = %s WHERE id = %s"
        )
        val = (
            "send to address",
            sender_info["address"],
            sender_info["username"],
            None,
            recipient_info["address"],
            str(response["amount"]),
            "cleared",
            entry_id,
        )
        tipper_functions.exec_sql(sql, val)
        LOGGER.info(
            f"Sending Nano: {sender_info['address']} {sender_info['private_key']} {response['amount']} {recipient_info['address']}"
        )
        return response

    # Update the sql and send the PMs
    sql = (
        "UPDATE history SET notes = %s, address = %s, username = %s, recipient_username = %s, "
        "recipient_address = %s, amount = %s, hash = %s, return_status = %s WHERE id = %s"
    )
    val = (
        "sent to user",
        sender_info["address"],
        sender_info["username"],
        recipient_info["username"],
        recipient_info["address"],
        str(response["amount"]),
        response["hash"],
        "cleared",
        entry_id,
    )
    tipper_functions.exec_sql(sql, val)
    LOGGER.info(
        f"Sending Nano: {sender_info['address']} {sender_info['private_key']} {response['amount']} {recipient_info['address']} {recipient_info['username']}"
    )

    if response["status"] == 20:
        subject = "Congrats on receiving your first Nano Tip!"
        message_text = (WELCOME_TIP % (
            response["amount"] / 10**30,
            recipient_info["address"],
            recipient_info["address"],
        ) + COMMENT_FOOTER)
        send_pm(recipient_info["username"], subject, message_text)
        return response
    else:
        if not recipient_info["silence"]:
            receiving_new_balance = check_balance(recipient_info["address"])
            subject = "You just received a new Nano tip!"
            message_text = (NEW_TIP % (
                response["amount"] / 10**30,
                recipient_info["address"],
                receiving_new_balance[0] / 10**30,
                receiving_new_balance[1] / 10**30,
                response["hash"],
            ) + COMMENT_FOOTER)
            send_pm(recipient_info["username"], subject, message_text)
        return response
コード例 #20
0
def handle_minimum(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    # user may select a minimum tip amount to avoid spamming. Tipbot minimum is 0.001
    username = str(message.author)
    # find any accounts associated with the redditor
    parsed_text = parse_text(str(message.body))

    # there should be at least 2 words, a minimum and an amount.
    if len(parsed_text) < 2:
        response = ("I couldn't parse your command. I was expecting 'minimum "
                    "<amount>'. Be sure to check your spacing.")
        return response
    # check that the minimum is a number

    if parsed_text[1].lower() == "nan" or ("inf" in parsed_text[1].lower()):
        response = ("'%s' didn't look like a number to me. If it is blank, "
                    "there might be extra spaces in the command.")
        return response
    try:
        amount = float(parsed_text[1])
    except:
        response = ("'%s' didn't look like a number to me. If it is blank, "
                    "there might be extra spaces in the command.")
        return response

    # check that it's greater than 0.01
    if nano_to_raw(amount) < nano_to_raw(PROGRAM_MINIMUM):
        response = (
            "Did not update. The amount you specified is below the program minimum "
            "of %s Nano." % PROGRAM_MINIMUM)
        return response

    # check if the user is in the database
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        # open_or_receive(result[0][0], result[0][1])
        # balance = check_balance(result[0][0])
        add_history_record(
            username=username,
            action="minimum",
            amount=nano_to_raw(amount),
            address=result[0][0],
            comment_or_message="message",
            comment_id=message.name,
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            comment_text=str(message.body)[:255],
        )
        sql = "UPDATE accounts SET minimum = %s WHERE username = %s"
        val = (str(nano_to_raw(amount)), username)
        MYCURSOR.execute(sql, val)
        MYDB.commit()
        response = "Updating tip minimum to %s" % amount
        return response
    else:
        add_history_record(
            username=username,
            action="minimum",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            amount=nano_to_raw(amount),
            comment_id=message.name,
            comment_text=str(message.body)[:255],
        )
        response = (
            "You do not currently have an account open. To create one, "
            "respond with the text 'create' in the message body.")
        return response
コード例 #21
0
def handle_message(message):
    response = "not activated"
    parsed_text = parse_text(str(message.body))
    command = parsed_text[0].lower()
    # only activate if it's not an opt-out command
    if command != "opt-out":
        activate(message.author)

    # normal commands
    if command in ["help", "!help"]:
        LOGGER.info("Helping")
        subject = "Nano Tipper - Help"
        response = handle_help(message)
    elif command in ["balance", "address"]:
        LOGGER.info("balance")
        subject = "Nano Tipper - Account Balance"
        response = handle_balance(message)
    elif command == "minimum":
        LOGGER.info("Setting Minimum")
        subject = "Nano Tipper - Tip Minimum"
        response = handle_minimum(message)
    elif command in ["percentage", "percent"]:
        LOGGER.info("Setting Percentage")
        subject = "Nano Tipper - Returned Tip Percentage for Donation"
        response = handle_percentage(message)
    elif command in ["create", "register"]:
        LOGGER.info("Creating")
        subject = "Nano Tipper - Create"
        response = handle_create(message)
    elif command in ["send", "withdraw"]:
        subject = "Nano Tipper - Send"
        LOGGER.info("send via PM")
        response = handle_send(message)
        response = text.make_response_text(message, response)
    elif command == "history":
        LOGGER.info("history")
        subject = "Nano Tipper - History"
        response = handle_history(message)
    elif command == "silence":
        LOGGER.info("silencing")
        subject = "Nano Tipper - Silence"
        response = handle_silence(message)
    elif command == "subreddit":
        LOGGER.info("subredditing")
        subject = "Nano Tipper - Subreddit"
        response = handle_subreddit(message)
    elif command == "opt-out":
        LOGGER.info("opting out")
        response = handle_opt_out(message)
        subject = "Nano Tipper - Opt Out"
    elif command == "opt-in":
        LOGGER.info("opting in")
        subject = "Nano Tipper - Opt In"
        response = handle_opt_in(message)

    # nanocenter donation commands
    elif command in ("project", "projects"):
        if (str(message.author).lower()
                in DONATION_ADMINS + TIPBOT_OWNER) and len(parsed_text) > 2:
            sql = "INSERT INTO projects (project, address) VALUES(%s, %s) ON DUPLICATE KEY UPDATE address=%s"
            val = (parsed_text[1], parsed_text[2], parsed_text[2])
            MYCURSOR.execute(sql, val)
            MYDB.commit()
        add_history_record(
            username=str(message.author),
            action="project",
            comment_text=str(message.body)[:255],
            comment_or_message="message",
            comment_id=message.name,
        )

        response = "Current NanoCenter Donation Projects: \n\n"
        subject = "Nanocenter Projects"
        sql = "SELECT project, address FROM projects"
        MYCURSOR.execute(sql)
        results = MYCURSOR.fetchall()
        for result in results:
            response += "%s %s  \n" % (result[0], result[1])
    elif command == "delete_project":
        if ((str(message.author) == TIPBOT_OWNER) or
            (str(message.author).lower()
             == "rockmsockmjesus")) and len(parsed_text) > 1:
            sql = "DELETE FROM projects WHERE project=%s"
            val = (parsed_text[1], )
            MYCURSOR.execute(sql, val)
            MYDB.commit()
        response = "Current NanoCenter Donation Projects: \n\n"
        subject = "Nanocenter Projects"
        sql = "SELECT project, address FROM projects"
        MYCURSOR.execute(sql)
        results = MYCURSOR.fetchall()
        for result in results:
            response += "%s %s  \n" % (result[0], result[1])
    # a few administrative tasks
    elif command in ["restart", "stop", "disable", "deactivate"]:
        if str(message.author).lower() in [
                TIPBOT_OWNER,
                "rockmsockmjesus",
        ]:  # "joohansson"]:
            add_history_record(
                username=str(message.author),
                action="restart",
                comment_text=str(message.body)[:255],
                comment_or_message="message",
                comment_id=message.name,
            )
            sys.exit()
    elif command == "test_welcome_tipped":
        subject = "Nano Tipper - Welcome By Tip"
        response = WELCOME_TIP % (
            0.01,
            "xrb_3jy9954gncxbhuieujc3pg5t1h36e7tyqfapw1y6zukn9y1g6dj5xr7r6pij",
            "xrb_3jy9954gncxbhuieujc3pg5t1h36e7tyqfapw1y6zukn9y1g6dj5xr7r6pij",
        )
    elif command == "test_welcome_create":
        subject = "Nano Tipper - Create"
        response = WELCOME_CREATE % (
            "xrb_3jy9954gncxbhuieujc3pg5t1h36e7tyqfapw1y6zukn9y1g6dj5xr7r6pij",
            "xrb_3jy9954gncxbhuieujc3pg5t1h36e7tyqfapw1y6zukn9y1g6dj5xr7r6pij",
        )

    else:
        add_history_record(
            username=str(message.author),
            comment_text=str(message.body)[:255],
            comment_or_message="message",
            comment_id=message.name,
        )
        return None
    message_recipient = str(message.author)
    message_text = response + COMMENT_FOOTER
    send_pm(message_recipient, subject, message_text, bypass_opt_out=True)
コード例 #22
0
def handle_history(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    username = str(message.author)
    parsed_text = parse_text(str(message.body))
    num_records = 10
    # if there are more than 2 words, one of the words is a number for the number of records
    if len(parsed_text) >= 2:
        if parsed_text[1].lower() == "nan" or ("inf"
                                               in parsed_text[1].lower()):
            response = (
                "'%s' didn't look like a number to me. If it is blank, "
                "there might be extra spaces in the command.")
            return response
        try:
            num_records = int(parsed_text[1])
        except:
            response = (
                "'%s' didn't look like a number to me. If it is blank, "
                "there might be extra spaces in the command.")
            return response

    # check that it's greater than 50
    if num_records > 50:
        num_records = 50

    # check if the user is in the database
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        # open_or_receive(result[0][0], result[0][1])
        # balance = check_balance(result[0][0])
        add_history_record(
            username=username,
            action="history",
            amount=num_records,
            address=result[0][0],
            comment_or_message="message",
            comment_id=message.name,
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            comment_text=str(message.body)[:255],
        )
        response = "Here are your last %s historical records:\n\n" % num_records
        sql = (
            "SELECT reddit_time, action, amount, comment_id, notes, recipient_"
            "username, recipient_address FROM history WHERE username=%s ORDER BY "
            "id DESC limit %s")
        val = (username, num_records)
        MYCURSOR.execute(sql, val)
        results = MYCURSOR.fetchall()
        for result in results:
            try:
                amount = result[2]
                if (result[1] == "send") and amount:
                    amount = int(result[2]) / 10**30
                    if (result[4] == "sent to registered redditor"
                            or result[4] == "new user created"):
                        response += (
                            "%s: %s | %s Nano to %s | reddit object: %s | %s\n\n"
                            % (
                                result[0],
                                result[1],
                                amount,
                                result[5],
                                result[3],
                                result[4],
                            ))
                    elif (result[4] == "sent to registered address"
                          or result[4] == "sent to unregistered address"):
                        response += (
                            "%s: %s | %s Nano to %s | reddit object: %s | %s\n\n"
                            % (
                                result[0],
                                result[1],
                                amount,
                                result[6],
                                result[3],
                                result[4],
                            ))
                elif result[1] == "send":
                    response += "%s: %s | reddit object: %s | %s\n\n" % (
                        result[0],
                        result[1],
                        result[3],
                        result[4],
                    )
                elif (result[1] == "minimum") and amount:
                    amount = int(result[2]) / 10**30
                    response += "%s: %s | %s | %s | %s\n\n" % (
                        result[0],
                        result[1],
                        amount,
                        result[3],
                        result[4],
                    )
                else:
                    response += "%s: %s | %s | %s | %s\n\n" % (
                        result[0],
                        result[1],
                        amount,
                        result[3],
                        result[4],
                    )
            except:
                response += (
                    "Unparsed Record: Nothing is wrong, I just didn't "
                    "parse this record properly.\n\n")

        return response
    else:
        add_history_record(
            username=username,
            action="history",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            amount=num_records,
            comment_id=message.name,
            comment_text=str(message.body)[:255],
        )
        response = (
            "You do not currently have an account open. To create one, "
            "respond with the text 'create' in the message body.")
        return response
コード例 #23
0
def handle_history(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    username = str(message.author)
    parsed_text = parse_text(str(message.body))
    num_records = 10
    # if there are more than 2 words, one of the words is a number for the number of records
    if len(parsed_text) >= 2:
        if parsed_text[1].lower() == "nan" or ("inf"
                                               in parsed_text[1].lower()):
            response = text.NAN
            return response
        try:
            num_records = int(parsed_text[1])
        except:
            response = text.NAN
            return response

    # check that it's greater than 50
    if num_records > 50:
        num_records = 50

    # check if the user is in the database
    try:
        acct = Account.get(username=username)
        # open_or_receive(result[0][0], result[0][1])
        # balance = check_balance(result[0][0])
        add_history_record(
            username=username,
            action="history",
            amount=num_records,
            address=acct.address,
            comment_or_message="message",
            comment_id=message.name,
            reddit_time=message_time,
            comment_text=str(message.body)[:255],
        )
        response = "Here are your last %s historical records:\n\n" % num_records
        history = History.select(
            History.reddit_time, History.action, History.amount,
            History.comment_id, History.notes, History.recipient_username,
            History.recipient_address).where(
                History.username == username).order_by(History.id.desc())
        for result in history:
            try:
                amount = result.amount
                if (result.action == "send") and amount:
                    amount = from_raw(int(result.amount))
                    if (result.notes == "sent to registered redditor"
                            or result.notes == "new user created"):
                        response += (
                            "%s: %s | %s Banano to %s | reddit object: %s | %s\n\n"
                            % (
                                result.reddit_time.strftime(
                                    "%Y-%m-%d %H:%M:%S"),
                                result.action,
                                amount,
                                result.recipient_username,
                                result.comment_id,
                                result.notes,
                            ))
                    elif (result.notes == "sent to registered address"
                          or result.notes == "sent to unregistered address"):
                        response += (
                            "%s: %s | %s Banano to %s | reddit object: %s | %s\n\n"
                            % (
                                result.reddit_time.strftime(
                                    "%Y-%m-%d %H:%M:%S"),
                                result.action,
                                amount,
                                result.recipient_address,
                                result.comment_id,
                                result.notes,
                            ))
                elif result.action == "send":
                    response += "%s: %s | reddit object: %s | %s\n\n" % (
                        result.reddit_time.strftime("%Y-%m-%d %H:%M:%S"),
                        result.action,
                        result.comment_id,
                        result.notes,
                    )
                else:
                    response += "%s: %s | %s | %s | %s\n\n" % (
                        result.reddit_time.strftime("%Y-%m-%d %H:%M:%S"),
                        result.action,
                        amount,
                        result.comment_id,
                        result.notes,
                    )
            except:
                response += (
                    "Unparsed Record: Nothing is wrong, I just didn't "
                    "parse this record properly.\n\n")

        return response
    except Account.DoesNotExist:
        add_history_record(
            username=username,
            action="history",
            reddit_time=message_time,
            amount=num_records,
            comment_id=message.name,
            comment_text=str(message.body)[:255],
        )
        response = text.NOT_OPEN
        return response
コード例 #24
0
def handle_percentage(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    # user may select a minimum tip amount to avoid spamming. Tipbot minimum is 0.001
    username = str(message.author)
    # find any accounts associated with the redditor
    parsed_text = parse_text(str(message.body))

    # there should be at least 2 words, a minimum and an amount.
    if len(parsed_text) < 2:
        response = "I couldn't parse your command. I was expecting 'percentage <amount>'. Be sure to check your spacing."
        return response
    # check that the minimum is a number

    if parsed_text[1].lower() == "nan" or ("inf" in parsed_text[1].lower()):
        response = "'%s' didn't look like a number to me. If it is blank, there might be extra spaces in the command."
        return response
    try:
        amount = float(parsed_text[1])
    except:
        response = "'%s' didn't look like a number to me. If it is blank, there might be extra spaces in the command."
        return response

    # check that it's greater than 0.01
    if round(amount, 2) < 0:
        response = "Did not update. Your percentage cannot be negative."
        return response

    if round(amount, 2) > 100:
        response = "Did not update. Your percentage must be 100 or lower."
        return response

    # check if the user is in the database
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        # open_or_receive(result[0][0], result[0][1])
        # balance = check_balance(result[0][0])
        add_history_record(
            username=username,
            action="percentage",
            amount=round(amount, 2),
            address=result[0][0],
            comment_or_message="message",
            comment_id=message.name,
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            comment_text=str(message.body)[:255],
        )
        sql = "UPDATE accounts SET percentage = %s WHERE username = %s"
        val = (round(amount, 2), username)
        MYCURSOR.execute(sql, val)
        MYDB.commit()
        response = "Updating donation percentage to %s" % round(amount, 2)
        return response
    else:
        add_history_record(
            username=username,
            action="percentage",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            amount=round(amount, 2),
            comment_id=message.name,
            comment_text=str(message.body)[:255],
        )
        response = (
            "You do not currently have an account open. To create one, "
            "respond with the text 'create' in the message body.")
        return response
コード例 #25
0
def send_from_comment(message):
    """
    Error codes:
    Success
    10 - sent to existing user
    20 - sent to new user
    30 - sent to address
    40 - donated to nanocenter project
    Tip not sent
    100 - sender account does not exist
    110 - Amount and/or recipient not specified
    120 - could not parse send amount
    130 - below program minimum
    140 - currency code issue
    150 - below 1 nano for untracked sub
    160 - insufficient funds
    170 - invalid address / recipient
    180 - below recipient minimum
    200 - No Nanocenter Project specified
    210 - Nanocenter Project does not exist



    Extracts send command information from a PM command
    :param message:
    :return: response string
    """

    parsed_text = parse_text(str(message.body))
    response = {"username": str(message.author)}
    message_time = datetime.datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    entry_id = add_history_record(
        username=response["username"],
        action="send",
        comment_or_message="comment",
        comment_id=message.name,
        reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
        comment_text=str(message.body)[:255],
    )

    # check if it's a donate command at the end
    if parsed_text[-3] in DONATE_COMMANDS:
        parsed_text = parsed_text[-3:]
    # don't do anything if the first word is a tip command or username
    elif (parsed_text[0] in [
            f"/u/{TIP_BOT_USERNAME}", f"u/{TIP_BOT_USERNAME}"
    ]) or (parsed_text[0] in TIP_COMMANDS):
        pass
    # if the second to last is a username or tip command, redifine parsed text
    elif (parsed_text[-2] in [
            f"/u/{TIP_BOT_USERNAME}", f"u/{TIP_BOT_USERNAME}"
    ]) or (parsed_text[-2] in TIP_COMMANDS):
        parsed_text = parsed_text[-2:]

    # before we can do anything, check the subreddit status for generating the response
    # check if amount is above subreddit minimum.
    response["subreddit"] = str(message.subreddit).lower()
    sql = "SELECT status FROM subreddits WHERE subreddit=%s"
    val = (response["subreddit"], )
    results = tipper_functions.query_sql(sql, val)
    if len(results) == 0:
        response["subreddit_minimum"] = 1
        results = [["untracked"]]
    elif results[0][0] in ["full", "friendly", "minimal", "silent"]:
        response["subreddit_minimum"] = 0
    else:
        response["subreddit_minimum"] = 1
    response["subreddit_status"] = results[0][0]

    # check that it wasn't a mistyped currency code or something
    if parsed_text[2] in EXCLUDED_REDDITORS:
        response["status"] = 140
        return response

    if parsed_text[0] in TIP_COMMANDS and len(parsed_text) <= 1:
        update_history_notes(entry_id, "no recipient or amount specified")
        response["status"] = 110
        return response

    if parsed_text[0] in DONATE_COMMANDS and len(parsed_text) <= 2:
        response["status"] = 110
        update_history_notes(entry_id, "no recipient or amount specified")
        return response

    # pull sender account info
    sender_info = tipper_functions.account_info(response["username"])
    if not sender_info:
        update_history_notes(entry_id, "user does not exist")
        response["status"] = 100
        return response

    # parse the amount
    try:
        response["amount"] = parse_raw_amount(parsed_text,
                                              response["username"])
    except TipError as err:
        response["status"] = 120
        response["amount"] = parsed_text[1]
        update_history_notes(entry_id, err.sql_text)
        return response

    # check if it's above the program minimum
    if response["amount"] < nano_to_raw(PROGRAM_MINIMUM):
        update_history_notes(entry_id, "amount below program limit")
        response["status"] = 130
        return response

    # check the user's balance
    if response["amount"] > sender_info["balance"]:
        update_history_notes(entry_id, "insufficient funds")
        response["status"] = 160
        return response

    if response["amount"] < nano_to_raw(response["subreddit_minimum"]):
        update_history_notes(entry_id, "amount below subreddit minimum")
        response["status"] = 150
        return response

    # if it's a normal send, pull the account author
    # we will distinguish users from donations by the presence of a private key
    if parsed_text[0] in (TIP_COMMANDS +
                          [f"/u/{TIP_BOT_USERNAME}", f"u/{TIP_BOT_USERNAME}"]):

        response["status"] = 10
        response["recipient"] = str(message.parent().author)
        recipient_info = tipper_functions.account_info(response["recipient"])
        if not recipient_info:
            response["status"] = 20
            recipient_info = tipper_functions.add_new_account(
                response["recipient"])
        elif recipient_info["silence"]:
            response["status"] = 11
        elif not recipient_info["opt_in"]:
            response["status"] = 190
            return response

    elif parsed_text[0] in DONATE_COMMANDS:
        response["recipient"] = parsed_text[2]
        results = tipper_functions.query_sql(
            "FROM projects SELECT address WHERE project = %s",
            (parsed_text[2], ))
        if len(results) <= 0:
            response["status"] = 210
            return response

        recipient_info = {
            "username": parsed_text[2],
            "address": results[0][0],
            "minimum": -1,
        }
        response["status"] = 40
    else:
        response["status"] = 999
        return response

    # check the send amount is above the user minimum, if a username is provided
    # if it was just an address, this would be -1
    if response["amount"] < recipient_info["minimum"]:
        update_history_notes(entry_id, "below user minimum")
        response["status"] = 180
        response["minimum"] = recipient_info["minimum"]
        return response

    # send the nanos!!
    response["hash"] = send(
        sender_info["address"],
        sender_info["private_key"],
        response["amount"],
        recipient_info["address"],
    )["hash"]

    # Update the sql and send the PMs
    sql = (
        "UPDATE history SET notes = %s, address = %s, username = %s, recipient_username = %s, "
        "recipient_address = %s, amount = %s, hash = %s, return_status = %s WHERE id = %s"
    )
    val = (
        "sent to user",
        sender_info["address"],
        sender_info["username"],
        recipient_info["username"],
        recipient_info["address"],
        str(response["amount"]),
        response["hash"],
        "cleared",
        entry_id,
    )
    tipper_functions.exec_sql(sql, val)
    LOGGER.info(
        f"Sending Nano: {sender_info['address']} {sender_info['private_key']} {response['amount']} {recipient_info['address']} {recipient_info['username']}"
    )

    # Update the sql and send the PMs if needed
    # if there is no private key, it's a donation. No PMs to send
    if "private_key" not in recipient_info.keys():
        sql = "UPDATE history SET notes = %s, address = %s, username = %s, recipient_address = %s, amount = %s WHERE id = %s"
        val = (
            "sent to nanocenter address",
            sender_info["address"],
            sender_info["username"],
            recipient_info["address"],
            str(response["amount"]),
            entry_id,
        )
        tipper_functions.exec_sql(sql, val)
        response["status"] = 40
        return response

    # update the sql database and send
    sql = (
        "UPDATE history SET notes = %s, address = %s, username = %s, recipient_username = %s, "
        "recipient_address = %s, amount = %s, return_status = %s WHERE id = %s"
    )
    val = (
        "sent to user",
        sender_info["address"],
        sender_info["username"],
        recipient_info["username"],
        recipient_info["address"],
        str(response["amount"]),
        "cleared",
        entry_id,
    )
    tipper_functions.exec_sql(sql, val)

    if response["status"] == 20:
        subject = "Congrats on receiving your first Nano Tip!"
        message_text = (text.WELCOME_TIP % (
            response["amount"] / 10**30,
            recipient_info["address"],
            recipient_info["address"],
        ) + text.COMMENT_FOOTER)
        send_pm(recipient_info["username"], subject, message_text)
        return response
    else:
        if not recipient_info["silence"]:
            receiving_new_balance = check_balance(recipient_info["address"])
            subject = "You just received a new Nano tip!"
            message_text = (text.NEW_TIP % (
                response["amount"] / 10**30,
                recipient_info["address"],
                receiving_new_balance[0] / 10**30,
                receiving_new_balance[1] / 10**30,
                response["hash"],
            ) + text.COMMENT_FOOTER)
            send_pm(recipient_info["username"], subject, message_text)
        return response
コード例 #26
0
def handle_message(message):
    response = "not activated"
    parsed_text = parse_text(str(message.body))
    command = parsed_text[0].lower()
    # only activate if it's not an opt-out command
    if command != "opt-out":
        activate(message.author)

    # normal commands
    if command in ["help", "!help"]:
        LOGGER.info("Helping")
        subject = text.SUBJECTS["help"]
        response = handle_help(message)
    elif command in ["balance", "address"]:
        LOGGER.info("balance")
        subject = text.SUBJECTS["balance"]
        response = handle_balance(message)
    elif command in ["create", "register"]:
        LOGGER.info("Creating")
        subject = text.SUBJECTS["create"]
        response = handle_create(message)
    elif command in ["send", "withdraw"]:
        subject = text.SUBJECTS["send"]
        LOGGER.info("send via PM")
        response = handle_send(message)
        response = text.make_response_text(message, response)
    elif command == "history":
        LOGGER.info("history")
        subject = text.SUBJECTS["history"]
        response = handle_history(message)
    elif command == "silence":
        LOGGER.info("silencing")
        subject = text.SUBJECTS["silence"]
        response = handle_silence(message)
    elif command == "subreddit":
        LOGGER.info("subredditing")
        subject = text.SUBJECTS["subreddit"]
        response = handle_subreddit(message)
    elif command == "opt-out":
        LOGGER.info("opting out")
        response = handle_opt_out(message)
        subject = text.SUBJECTS["opt-out"]
    elif command == "opt-in":
        LOGGER.info("opting in")
        subject = text.SUBJECTS["opt-in"]
        response = handle_opt_in(message)
    # a few administrative tasks
    elif command in ["restart", "stop", "disable", "deactivate"]:
        if str(message.author).lower() in [
                TIPBOT_OWNER,
        ]:  # "joohansson"]:
            add_history_record(
                username=str(message.author),
                action="restart",
                comment_text=str(message.body)[:255],
                comment_or_message="message",
                comment_id=message.name,
            )
            sys.exit()
    else:
        add_history_record(
            username=str(message.author),
            comment_text=str(message.body)[:255],
            comment_or_message="message",
            comment_id=message.name,
        )
        return None
    message_recipient = str(message.author)
    message_text = response + COMMENT_FOOTER
    send_pm(message_recipient, subject, message_text, bypass_opt_out=True)
コード例 #27
0
def handle_send(message):
    """
    Extracts send command information from a PM command
    :param message:
    :return:
    """
    parsed_text = parse_text(str(message.body))
    username = str(message.author)
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    entry_id = add_history_record(
        username=username,
        action="send",
        comment_or_message="message",
        comment_id=message.name,
        reddit_time=message_time,
        comment_text=str(message.body)[:255],
    )
    response = {"username": username}

    # check that there are enough fields (i.e. a username)
    if len(parsed_text) <= 2:
        update_history_notes(entry_id, "no recipient or amount specified")
        response["status"] = 110
        return response

    # pull sender account info
    sender_info = tipper_functions.account_info(response["username"])
    if not sender_info:
        update_history_notes(entry_id, "user does not exist")
        response["status"] = 100
        return response

    # parse the amount
    try:
        response["amount"] = parse_raw_amount(parsed_text,
                                              response["username"])
    except TipError as err:
        response["status"] = 120
        response["amount"] = parsed_text[1]
        update_history_notes(entry_id, err.sql_text)
        return response

    # check if it's above the program minimum
    if response["amount"] < to_raw(PROGRAM_MINIMUM):
        update_history_notes(entry_id, "amount below program limit")
        response["status"] = 130
        return response

    # check the user's balance
    if response["amount"] > sender_info["balance"]:
        update_history_notes(entry_id, "insufficient funds")
        response["status"] = 160
        return response

    recipient_text = parsed_text[2]

    # catch invalid redditor AND address
    try:
        recipient_info = parse_recipient_username(recipient_text)
    except TipError as err:
        update_history_notes(entry_id, err.sql_text)
        response["recipient"] = recipient_text
        response["status"] = 170
        return response

    # if we have a username, pull their info
    if "username" in recipient_info.keys():
        response["recipient"] = recipient_info["username"]
        recipient_name = recipient_info["username"]
        recipient_info = tipper_functions.account_info(recipient_name)
        response["status"] = 10
        if recipient_info is None:
            recipient_info = tipper_functions.add_new_account(
                response["recipient"])
            if recipient_info is None:
                return text.TIP_CREATE_ACCT_ERROR
            response["status"] = 20
        elif not recipient_info["opt_in"]:
            response["status"] = 190
            return response
    # check if it's an address
    else:
        # otherwise, just use the address. Everything is None except address
        response["recipient"] = recipient_info["address"]
        response["status"] = 30

    if sender_info["address"] == recipient_info["address"]:
        # Don't allow sends to yourself
        response["status"] = 200
        return response

    response["hash"] = send(
        sender_info["address"],
        response["amount"],
        recipient_info["address"],
    )["block"]
    # if it was an address, just send to the address
    if "username" not in recipient_info.keys():
        History.update(
            notes="send to address",
            address=sender_info["address"],
            username=sender_info["username"],
            recipient_username=None,
            recipient_address=recipient_info["address"],
            amount=str(response["amount"]),
            return_status="cleared").where(History.id == entry_id).execute()
        LOGGER.info(
            f"Sending Banano: {sender_info['address']} {sender_info['private_key']} {response['amount']} {recipient_info['address']}"
        )
        return response

    # Update the sql and send the PMs
    History.update(
        notes="send to address",
        address=sender_info["address"],
        username=sender_info["username"],
        recipient_username=recipient_info["username"],
        recipient_address=recipient_info["address"],
        amount=str(response["amount"]),
        return_status="cleared").where(History.id == entry_id).execute()
    LOGGER.info(
        f"Sending Banano: {sender_info['address']} {sender_info['private_key']} {response['amount']} {recipient_info['address']} {recipient_info['username']}"
    )

    if response["status"] == 20:
        subject = text.SUBJECTS["first_tip"]
        message_text = (WELCOME_TIP % (
            NumberUtil.format_float(from_raw(response["amount"])),
            recipient_info["address"],
            recipient_info["address"],
        ) + COMMENT_FOOTER)
        send_pm(recipient_info["username"], subject, message_text)
        return response
    else:
        if not recipient_info["silence"]:
            receiving_new_balance = check_balance(recipient_info["address"])
            subject = text.SUBJECTS["new_tip"]
            message_text = (NEW_TIP % (
                NumberUtil.format_float(from_raw(response["amount"])),
                recipient_info["address"],
                from_raw(receiving_new_balance),
                response["hash"],
            ) + COMMENT_FOOTER)
            send_pm(recipient_info["username"], subject, message_text)
        return response
コード例 #28
0
def send_from_comment(message):
    """
    Error codes:
    Success
    10 - sent to existing user
    20 - sent to new user
    30 - sent to address
    40 - donated to nanocenter project
    Tip not sent
    100 - sender account does not exist
    110 - Amount and/or recipient not specified
    120 - could not parse send amount
    130 - below program minimum
    150 - below 1 nano for untracked sub
    160 - insufficient funds
    170 - invalid address / recipient
    180 - below recipient minimum
    200 - No Nanocenter Project specified
    210 - Nanocenter Project does not exist



    Extracts send command information from a PM command
    :param message:
    :return: response string
    """

    parsed_text = parse_text(str(message.body))
    response = {"username": str(message.author)}
    message_time = datetime.datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    entry_id = add_history_record(
        username=response["username"],
        action="send",
        comment_or_message="comment",
        comment_id=message.name,
        reddit_time=message_time,
        comment_text=str(message.body)[:255],
    )

    # don't do anything if the first word is a tip command or username
    if (parsed_text[0] in [f"/u/{TIP_BOT_USERNAME}", f"u/{TIP_BOT_USERNAME}"
                           ]) or (parsed_text[0] in TIP_COMMANDS):
        pass
    # if the second to last is a username or tip command, redifine parsed text
    elif (parsed_text[-2] in [
            f"/u/{TIP_BOT_USERNAME}", f"u/{TIP_BOT_USERNAME}"
    ]) or (parsed_text[-2] in TIP_COMMANDS):
        parsed_text = parsed_text[-2:]

    # before we can do anything, check the subreddit status for generating the response
    response["subreddit"] = str(message.subreddit).lower()
    try:
        sr = Subreddit.select(Subreddit.status, Subreddit.minimum).where(
            Subreddit.subreddit == response["subreddit"]).get()
        response["subreddit_status"] = sr.status
        response["subreddit_minimum"] = sr.minimum
    except Subreddit.DoesNotExist:
        response["subreddit_status"] = "untracked"
        response["subreddit_minimum"] = "1"

    if parsed_text[0] in TIP_COMMANDS and len(parsed_text) <= 1:
        update_history_notes(entry_id, "no recipient or amount specified")
        response["status"] = 110
        return response

    # pull sender account info
    sender_info = tipper_functions.account_info(response["username"])
    if not sender_info:
        update_history_notes(entry_id, "user does not exist")
        response["status"] = 100
        return response

    # parse the amount
    try:
        response["amount"] = parse_raw_amount(parsed_text,
                                              response["username"])
    except TipError as err:
        response["status"] = 120
        response["amount"] = parsed_text[1]
        update_history_notes(entry_id, err.sql_text)
        return response

    # check if it's above the program minimum
    if response["amount"] < to_raw(PROGRAM_MINIMUM):
        update_history_notes(entry_id, "amount below program limit")
        response["status"] = 130
        return response

    # check the user's balance
    if response["amount"] > sender_info["balance"]:
        update_history_notes(entry_id, "insufficient funds")
        response["status"] = 160
        return response

    # check that it's above the subreddit minimum
    if response["amount"] < to_raw(response["subreddit_minimum"]):
        update_history_notes(entry_id, "amount below subreddit minimum")
        response["status"] = 150
        return response

    # if it's a normal send, pull the account author
    # we will distinguish users from donations by the presence of a private key
    if parsed_text[0] in (TIP_COMMANDS +
                          [f"/u/{TIP_BOT_USERNAME}", f"u/{TIP_BOT_USERNAME}"]):

        response["status"] = 10
        response["recipient"] = str(message.parent().author)
        recipient_info = tipper_functions.account_info(response["recipient"])
        if not recipient_info:
            response["status"] = 20
            recipient_info = tipper_functions.add_new_account(
                response["recipient"])
            if recipient_info is None:
                return text.TIP_CREATE_ACCT_ERROR
        elif recipient_info["silence"]:
            response["status"] = 11
        elif not recipient_info["opt_in"]:
            response["status"] = 190
            return response
    else:
        response["status"] = 999
        return response

    if sender_info["address"] == recipient_info["address"]:
        # Don't allow sends to yourself
        response["status"] = 200
        return response

    # send the bans!!
    response["hash"] = send(
        sender_info["address"],
        response["amount"],
        recipient_info["address"],
    )["block"]

    # Update the sql and send the PMs
    History.update(
        notes="sent to user",
        address=sender_info["address"],
        username=sender_info["username"],
        recipient_username=recipient_info["username"],
        recipient_address=recipient_info["address"],
        amount=str(response["amount"]),
        hash=response["hash"],
        return_status="cleared").where(History.id == entry_id).execute()

    LOGGER.info(
        f"Sending Banano: {sender_info['address']} {sender_info['private_key']} {response['amount']} {recipient_info['address']} {recipient_info['username']}"
    )

    if response["status"] == 20:
        subject = text.SUBJECTS["first_tip"]
        message_text = (text.WELCOME_TIP % (
            NumberUtil.format_float(from_raw(response["amount"])),
            recipient_info["address"],
            recipient_info["address"],
        ) + text.COMMENT_FOOTER)
        send_pm(recipient_info["username"], subject, message_text)
        return response
    else:
        if not recipient_info["silence"]:
            receiving_new_balance = check_balance(recipient_info["address"])
            subject = text.SUBJECTS["new_tip"]
            message_text = (text.NEW_TIP % (
                NumberUtil.format_float(from_raw(response["amount"])),
                recipient_info["address"],
                from_raw(receiving_new_balance),
                response["hash"],
            ) + text.COMMENT_FOOTER)
            send_pm(recipient_info["username"], subject, message_text)
        return response
コード例 #29
0
def handle_minimum(message):
    message_time = datetime.utcfromtimestamp(
        message.created_utc)  # time the reddit message was created
    # user may select a minimum tip amount to avoid spamming. Tipbot minimum is 0.001
    username = str(message.author)
    # find any accounts associated with the redditor
    parsed_text = parse_text(str(message.body))

    # there should be at least 2 words, a minimum and an amount.
    if len(parsed_text) < 2:
        response = text.MINIMUM["parse_error"]
        return response
    # check that the minimum is a number

    if parsed_text[1].lower() == "nan" or ("inf" in parsed_text[1].lower()):
        response = text.NAN
        return response
    try:
        amount = float(parsed_text[1])
    except:
        response = text.NAN % parsed_text[1]
        return response

    # check that it's greater than 0.01
    if to_raw(amount) < to_raw(PROGRAM_MINIMUM):
        response = text.MINIMUM["below_program"] % PROGRAM_MINIMUM
        return response

    # check if the user is in the database
    sql = "SELECT address FROM accounts WHERE username=%s"
    val = (username, )
    MYCURSOR.execute(sql, val)
    result = MYCURSOR.fetchall()
    if len(result) > 0:
        # open_or_receive(result[0][0], result[0][1])
        # balance = check_balance(result[0][0])
        add_history_record(
            username=username,
            action="minimum",
            amount=to_raw(amount),
            address=result[0][0],
            comment_or_message="message",
            comment_id=message.name,
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            comment_text=str(message.body)[:255],
        )
        sql = "UPDATE accounts SET minimum = %s WHERE username = %s"
        val = (str(to_raw(amount)), username)
        MYCURSOR.execute(sql, val)
        MYDB.commit()
        response = text.MINIMUM["set_min"] % amount
        return response
    else:
        add_history_record(
            username=username,
            action="minimum",
            reddit_time=message_time.strftime("%Y-%m-%d %H:%M:%S"),
            amount=to_raw(amount),
            comment_id=message.name,
            comment_text=str(message.body)[:255],
        )
        response = text.NOT_OPEN
        return response