Пример #1
0
def add_type_to_sale(user, channel, command, purchase_id):
    # check that a type was indicated in the command
    response = "something went wrong - add_type_to_sale"

    db = database.Database()
    # get supported coins
    supported_coins = db.fetchAll(
        "select * from supported_coins order by sort_order desc")
    db.close()

    # did user give type?
    coin = None
    for supported_coin in supported_coins:
        if supported_coin["coin_name"].lower() in command:
            coin = supported_coin["coin_id"]
            break

    if coin == None:
        response = "Sorry, you didn't give me a valid crypto type."
        bot_utilities.log_event("expected coin type and failed:" + user +
                                ": " + command)

    else:
        db = database.Database()
        db.runSql(
            """update sales set coin_type = %s, last_updated = now(), step = "amount" where purchase_id = %s""",
            [coin, purchase_id])
        db.close()
        response = "Sounds great.  How much " + coin.upper() + " did you sell?"

    bot_utilities.post_to_channel(channel, response)
Пример #2
0
def show_prices(user, channel, command):
    response = ""

    db = database.Database()
    coins = db.fetchAll(
        "select * from supported_coins order by sort_order asc")

    for coin in coins:
        # fetch the previous pice
        records = db.fetchAll(
            """select * 
                                from price_history 
                                where coin = %s and date > now()-interval 24 hour order by date asc limit 1""",
            [coin['coin_id']])

        current_price = bot_utilities.get_current_price(
            coin['coin_id'].lower())

        try:  # in case prices didn't get logged
            start_price = records[0]['price']
            change_pct = bot_utilities.floored_percentage(
                (current_price - float(start_price)) / float(start_price), 2)

        except:
            start_price = 0
            change_pct = "error"

        # add to response
        response = response + "*" + coin['coin_id'] + " " + coin[
            'coin_name'] + ":* $" + str(current_price) + " _(" + str(
                change_pct) + ")_ \n"

    bot_utilities.post_to_channel(channel, response)

    bot_utilities.log_event(user + " requested prices: " + command)
Пример #3
0
def list_transactions(user, channel, command):
    response = "something went wrong - list_transactions"

    db = database.Database()
    records = db.fetchAll(
        """
                            select *, "purchase" as type 
                            from purchases 
                            where user_id = %s and record_complete = 1

                            union

                            select * , "sale" as type
                            from sales 
                            where user_id = %s and record_complete = 1
                            """, [user, user])
    db.close()

    response = "ID | trans | coin | amount | USD | date \n"

    for record in records:
        response = response + str(record["purchase_id"]) + " | " + record[
            "type"] + " | " + record["coin_type"].upper() + " | " + str(
                record["amount"]) + " | $" + str(
                    record["usd_spent"]) + " | " + str(record["date"]) + "\n"

    bot_utilities.post_to_channel(channel, response)
    bot_utilities.log_event(user + " listed transactions")
Пример #4
0
def delete_transaction(user, channel, command, type="purchase"):
    response = "something went wrong - delete_transaction"

    # make sure we have a number in the command
    trans_number = bot_utilities.parse_number_from_command(command)

    if trans_number == -9999:
        response = "You need to give me a transaction number.  \"List Transactions\" will show you a list of your transactions."
        bot_utilities.log_event(
            user +
            " attempted to delete a transaction but provided no transaction number: "
            + command)

    else:  # we have a transaction
        db = database.Database()
        if type == "purchase":
            records = db.fetchAll(
                """select * from purchases where purchase_id = %s and user_id = %s""",
                [trans_number, user])

            # verify that we have a record
            if len(records) == 0:
                response = "You need to give me a valid transaction number.  \"List Transactions\" will show you a list of your transactions."
                bot_utilities.log_event(
                    user +
                    " attempted to delete a transaction but provided an invalid transaction number: "
                    + command)

            else:  # delete the record
                db.runSql("""delete from purchases where purchase_id = %s""",
                          [records[0]["purchase_id"]])
                response = "Alright, that record has been deleted."
                bot_utilities.log_event(user + " has deleted a transaction: " +
                                        command)

        else:  # type is sale
            records = db.fetchAll(
                """select * from sales where purchase_id = %s and user_id = %s""",
                [trans_number, user])

            # verify that we have a record
            if len(records) == 0:
                response = "You need to give me a valid transaction number.  \"List Transactions\" will show you a list of your transactions."
                bot_utilities.log_event(
                    user +
                    " attempted to delete a transaction but provided an invalid transaction number: "
                    + command)

            else:  # delete the record
                db.runSql("""delete from sales where purchase_id = %s""",
                          [records[0]["purchase_id"]])
                response = "Alright, that record has been deleted."
                bot_utilities.log_event(user + " has deleted a transaction: " +
                                        command)

        db.close()
    bot_utilities.post_to_channel(channel, response)
Пример #5
0
def whats_balance(user, channel, command):
    response = "something went wrong - balance"
    wallets = bot_utilities.wallet_ballance(user)

    response = "Wallets:\n"
    for wallet in wallets:
        current_value = bot_utilities.get_current_price(
            wallet["coin_type"]) * float(wallet["balance"])
        response = response + "*" + wallet["coin_type"].upper(
        ) + " " + wallet["coin_name"] + ":* " + str(round(
            wallet["balance"], 8)) + " _($" + str(round(current_value,
                                                        2)) + ")_\n"

    bot_utilities.log_event(user + " requested wallet balances: " + command)
    bot_utilities.post_to_channel(channel, response)
Пример #6
0
def server_report(user, channel, command):
    response = "generating server report: \n"
    db = database.Database()
    # get list of users
    coin_users = db.fetchAll("select distinct p.user_id from purchases p")

    # for each user, call the profit command
    for coin_user in coin_users:
        user_name = bot_utilities.get_slack_name(coin_user['user_id'])
        response = response + "*" + user_name + ":* \n"
        bot_utilities.post_to_channel(channel, response)
        provide_profit_info(coin_user['user_id'], channel, command)
        response = ""

    bot_utilities.log_event(user + " requested a server report")
    db.close()
Пример #7
0
def add_amount_to_sale(user, channel, command, purchase_id):
    response = "something went wrong - add_amount_to_sale"

    # try to get the number from the command
    parsed_amount = bot_utilities.parse_number_from_command(command)

    if parsed_amount == -9999:  # cound't get the number
        response = "sorry, I didn't catch that.  How much did you sell?"
        bot_utilities.log_event(
            "trying to add amount to sale and didn't parse number." + user +
            ": " + command)

    else:  # update the record and move on
        db = database.Database()
        db.runSql(
            """update sales set amount = %s, last_updated = now(), step = "usd_gained" where purchase_id = %s""",
            [parsed_amount, purchase_id])
        response = "Great.  How much USD did you get in return?"
        db.close()

    bot_utilities.post_to_channel(channel, response)
Пример #8
0
def add_usd_to_purchase(user, channel, command, purchase_id):
    response = "something went wrong - add_usd_to_purchase"

    # try to get the number from the command
    parsed_amount = bot_utilities.parse_number_from_command(command)

    if parsed_amount == -9999:  # cound't get the number
        response = "sorry, I didn't catch that.  How much money did you spend?"
        bot_utilities.log_event(
            "trying to add usd to purchase and didn't parse number." + user +
            ": " + command)

    else:  # update the record and move on
        db = database.Database()
        db.runSql(
            """update purchases set usd_spent = %s, last_updated = now(), record_complete = 1, step = "complete" where purchase_id = %s""",
            [parsed_amount, purchase_id])
        response = "Great, you're all set."
        bot_utilities.log_event(user + " added a purchase")
        db.close()

    bot_utilities.post_to_channel(channel, response)
Пример #9
0
def add_sale(user, channel, command):
    db = database.Database()
    response = "something went wrong - add_sale"
    # verify no current record is incomplete.  If so, blow it away
    db.runSql(
        """delete from sales where record_complete = 0 and user_id = %s""",
        [user])

    # get supported coins
    supported_coins = db.fetchAll(
        "select * from supported_coins order by sort_order desc")

    # did user give type?
    coin = None
    for supported_coin in supported_coins:
        if supported_coin["coin_name"].lower() in command:
            coin = supported_coin["coin_id"]
            break

    # begin sale record
    if coin != None:
        db.runSql(
            """insert into sales (user_id, date, coin_type, step, last_updated) values(%s, now(), %s, "amount",now())""",
            [user, coin])
        response = "Sounds great.  How much " + coin.upper() + " did you sell?"

    else:
        db.runSql(
            """insert into sales (user_id, date, step, last_updated) values(%s, now(), "type",now())""",
            [user])
        response = "Sounds great.  What type of crypto did you sell"

    # log event
    bot_utilities.log_event(user + " has begun a sale record: " + command)

    # message user
    bot_utilities.post_to_channel(channel, response)
Пример #10
0
def parse_slack_output(slack_rtm_output):
    """
        The Slack Real Time Messaging API is an events firehose.
        this parsing function returns None unless a message is
        directed at the Bot, based on its ID.
    """
    try:
        output_list = slack_rtm_output
        if output_list and len(output_list) > 0:
            for output in output_list:
                #print ("\n")
                #print(output)
                #print ("\n")

                try:  # ensure the message has a user and text
                    text = output['text']
                    user = output['user']
                except:
                    return None, None, None, None

                if output and 'text' in output and AT_BOT in output['text']:
                    # return text after the @ mention, whitespace removed
                    output['text'] = output['text'].replace(u"\u2019", '\'')
                    return output['text'].split(AT_BOT)[1].strip().lower(), \
                           output['channel'], \
                           output['user'], \
                           output['text'].split(AT_BOT)[1].strip()

                #handle im conversations without needing @
                elif output and 'text' in output and output[
                        'user'] != BOT_ID and output['user'] != "USLACKBOT":
                    output['text'] = output['text'].replace(u"\u2019", '\'')

                    response = slack_client.api_call("im.list")
                    ims = response["ims"]
                    for im in ims:
                        if im["id"] == output['channel']:
                            return output['text'].lower(), \
                                   output['channel'], \
                                   output['user'], \
                                   output['text']
        return None, None, None, None

    except:  # nested tries to prevent the bot from crashing
        bot_utilities.log_event(
            "An unhandled error was encountered - parse_slack_output")
        try:
            bot_utilities.log_event(output['channel'] + " " + output['user'])
            return None, None, None, None
        except:
            bot_utilities.log_event("failed to log the unhandled error")
            return None, None, None, None
Пример #11
0
def handle_command(command, channel, user, command_orig):
    """
        Receives commands directed at the bot and determines if they
        are valid commands. If so, then acts on the commands. If not,
        returns back what it needs for clarification.
    """
    db = database.Database()
    response = "Sorry, I'm kind of a dumb robot.  I have no idea what you mean. Type 'help' to learn about me"
    deffered = False

    if command.startswith('hi') or command.startswith('hello'):
        response = "well hello there!"

    # user wants to know possible commands
    elif command.startswith('help'):
        response = """
You can use the following commands:\n
_______\n
*HOW AM I DOING?*: tells you your current crypto profit\n
*WHAT'S MY BALANCE?*: lists your current crypto balance\n
*I BOUGHT ___*: tell me when you buy crypto\n
*I SOLD ___*: tell me when you sell crypto\n
*SHOW MY TRANSACTIONS*: lists your transactions\n
*DELETE PURCHASE #*: deletes indicated purchase transaction\n
*DELETE SALE #*: deletes indicated sale transaction\n
 \n
_tip: if you need to remove coin due to fees, log a sale for $0_\n
_______\n
                    """

    elif command.startswith('how am i doing'):
        bot_commands.provide_profit_info(user, channel, command)
        deffered = True

    elif 'balance' in command:
        bot_commands.whats_balance(user, channel, command)
        deffered = True

    elif command.startswith('server report'):
        bot_commands.server_report(user, channel, command)
        deffered = True

    elif command.startswith('i bought'):
        bot_commands.add_purchase(user, channel, command)
        deffered = True

    elif command.startswith('i sold'):
        bot_commands.add_sale(user, channel, command)
        deffered = True

    elif ('show' in command or 'list' in command) and 'transaction' in command:
        bot_commands.list_transactions(user, channel, command)
        deffered = True

    elif ('list' in command or 'show' in command) and 'price' in command:
        bot_commands.show_prices(user, channel, command)
        deffered = True

    elif command.startswith('delete purchase'):
        bot_commands.delete_transaction(user, channel, command, "purchase")
        deffered = True

    elif command.startswith('delete sale'):
        bot_commands.delete_transaction(user, channel, command, "sale")
        deffered = True

    elif command.startswith("go kill yourself") and user == admin_user:
        bot_utilities.log_event("self destruct activated")
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text="wow, that's rude",
                              as_user=True)
        sys.exit()

    elif bot_utilities.user_is_adding_record(
            user, "purchase"
    ):  # determine if the user is currently working to create a purchase record
        bot_commands.handle_ongoing_record_creation(user, channel, command,
                                                    "purchase")
        deffered = True

    elif bot_utilities.user_is_adding_record(
            user, "sale"
    ):  # determine if the user is currently working to create a sale record
        bot_commands.handle_ongoing_record_creation(user, channel, command,
                                                    "sale")
        deffered = True

    if deffered == False:
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=response,
                              as_user=True)
    db.close()
Пример #12
0
    except:  # nested tries to prevent the bot from crashing
        bot_utilities.log_event(
            "An unhandled error was encountered - parse_slack_output")
        try:
            bot_utilities.log_event(output['channel'] + " " + output['user'])
            return None, None, None, None
        except:
            bot_utilities.log_event("failed to log the unhandled error")
            return None, None, None, None


if __name__ == "__main__":
    READ_WEBSOCKET_DELAY = 1  # 1 second delay between reading from firehose

    if slack_client.rtm_connect():
        bot_utilities.log_event("Bitcoin Bot connected and running!")
        while True:
            command, channel, user, command_orig = parse_slack_output(
                slack_client.rtm_read())
            if command and channel:
                handle_command(command, channel, user, command_orig)

            time.sleep(READ_WEBSOCKET_DELAY)
    else:
        bot_utilities.log_event(
            "Connection failed. Invalid Slack token or bot ID?")

# use this to get your bot ID for the config file

#BOT_NAME = 'og_bot'
#
Пример #13
0
def provide_profit_info(user, channel, command):
    response = "something went wrong - provide_profit_info"

    # get the user's current ballance
    wallets = bot_utilities.wallet_ballance(user)

    db = database.Database()
    # get supported coins
    coins = db.fetchAll(
        "select *, 0.0 as current_value, 0.0 as current_worth from supported_coins"
    )

    # find the current rates
    for coin in coins:
        coin['current_value'] = Decimal(
            bot_utilities.get_current_price(coin['coin_id'].lower()))

    total_spent = 0
    total_worth = 0
    cashed_out = 0

    # match the wallets with the coins and populate the current worth
    for wallet in wallets:
        for coin in coins:
            if wallet["coin_type"].lower() == coin["coin_id"].lower():
                wallet["current_worth"] = wallet["balance"] * coin[
                    "current_value"]
                break
        #sum total spent and worth
        total_spent = total_spent + wallet["usd_spent"]
        total_worth = total_worth + wallet["current_worth"]
        cashed_out = cashed_out + wallet["usd_gained"]

    total_worth = round(total_worth, 2)
    total_change = round(Decimal(total_worth - float(total_spent)),
                         2)  # worth-spent

    # fetch the values to compare to day/month
    day_record = db.fetchAll(
        """select user_id, total_spent, total_value 
                                from performance_log 
                                where user_id = %s and date > now() - interval 24 hour
                                order by date asc limit 1""", [user])

    # get the change in value for the day
    try:
        # day_gain = abs(day_record[0]["total_value"]) - abs(day_record[0]["total_spent"])
        # day_change_dec = ((Decimal(total_worth) + cashed_out -total_spent) - day_gain ) / day_gain
        # day_change = bot_utilities.floored_percentage(day_change_dec,2) # format to percentage

        usd_spent_today = bot_utilities.usd_spent_in_x_days(user, 1)

        gain_from_yesterday = (
            Decimal(total_worth) + cashed_out
        ) - day_record[0][
            "total_value"] - usd_spent_today  # today's worth minus what the worth was yesterday
        day_change = bot_utilities.floored_percentage(
            gain_from_yesterday / day_record[0]["total_value"],
            2)  # get a perceent change

        day_growth_str = "$" + str(round(gain_from_yesterday, 2))

    except:
        day_change = ""
        day_growth_str = "error"

    month_record = db.fetchAll(
        """select user_id, total_spent, total_value 
                                from performance_log 
                                where user_id = %s and date > now() - interval 30 day
                                order by date asc limit 1""", [user])

    # get the change in value for the month
    try:
        # last_month_gain = month_record[0]["total_value"] - month_record[0]["total_spent"] # what the gain was last month
        # month_change_dec = ((Decimal(total_worth) + cashed_out - total_spent) - last_month_gain ) / last_month_gain # compare the last month's gain to today's gain
        # month_change = bot_utilities.floored_percentage(month_change_dec,2) # format to percentage

        usd_spent_this_month = bot_utilities.usd_spent_in_x_days(user, 30)

        gain_from_last_month = (
            Decimal(total_worth) + cashed_out
        ) - month_record[0][
            "total_value"] - usd_spent_this_month  # today's worth minus what the worth was last month
        month_change = bot_utilities.floored_percentage(
            gain_from_last_month / month_record[0]["total_value"],
            2)  # get a perceent change

        month_growth_str = "$" + str(round(gain_from_last_month, 2))

    except:
        month_change = ""
        month_growth_str = "error"

    db.close()

    value_plus_cashed = round(Decimal(total_change) + cashed_out,
                              2)  # combine our wallet and our cashed out

    response = "*Spent:* $" + str(total_spent)+ "\n" \
        "*Value:* $" + str(total_worth) + "\n" \
        "*Cashed Out:* $" + str(cashed_out) + "\n" \
        "*CHANGE:* $" + str(value_plus_cashed) + " _(" + bot_utilities.floored_percentage((Decimal(value_plus_cashed)/total_spent),2) + ")_ \n \n" \
        "_growth today: "+ day_growth_str + " (" + day_change + ")_\n" \
        "_30 day growth: " + month_growth_str + " (" + month_change+")_"

    bot_utilities.log_event(user + " requested performance: " + command)
    bot_utilities.post_to_channel(channel, response)