Exemplo n.º 1
0
def edit_user_config(update: Update, _: CallbackContext) -> int:
    logger.info(f"Editing user configuration. ({update.message.text})")

    if update.message.text != "/stop":
        message = (f"✔ Successfully edited user configuration file to:\n\n"
                   f"```\n"
                   f"{update.message.text}\n"
                   f"```".replace(".", "\."))
        user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
        try:
            copyfile(user_cfg_file_path, f"{user_cfg_file_path}.backup")
            with open(user_cfg_file_path, "w") as f:
                f.write(update.message.text + "\n\n\n")
        except Exception as e:
            logger.error(f"❌ Unable to edit user configuration file: {e}")
            message = "❌ Unable to edit user configuration file\."
    else:
        message = ("👌 Exited without changes\.\n"
                   "Your `user.cfg` file was *not* modified\.")

    keyboard = [["Go back"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    update.message.reply_text(message,
                              reply_markup=reply_markup,
                              parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 2
0
def find_and_kill_binance_trade_bot_process():
    try:
        binance_trade_bot_process = get_binance_trade_bot_process()
        binance_trade_bot_process.terminate()
        binance_trade_bot_process.wait()
    except Exception as e:
        logger.info(f"ERROR: {e}")
Exemplo n.º 3
0
def update_btb(update: Update, _: CallbackContext) -> int:
    logger.info(f"Updating Binance Trade Bot. ({update.message.text})")

    keyboard = [["OK 👌"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)

    if update.message.text != "Cancel update":
        message = ("The bot has been stopped and is now updating\.\n"
                   "Wait a few seconds, then restart manually\.")
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")
        try:
            find_and_kill_binance_trade_bot_process()
            subprocess.call(
                f"cd {settings.ROOT_PATH} && "
                f"git pull && "
                f"$(which python3) -m pip install -r requirements.txt --upgrade",
                shell=True,
            )
        except Exception as e:
            logger.error(f"Unable to update Binance Trade Bot: {e}")
            message = "Unable to update Binance Trade Bot"
            update.message.reply_text(message,
                                      reply_markup=reply_markup,
                                      parse_mode="MarkdownV2")
    else:
        message = "👌 Exited without changes\.\n" "Binance Trade Bot was *not* updated\."
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 4
0
def edit_user_cfg():
    logger.info("Edit user configuration button pressed.")

    message = "⚠ Please stop Binance Trade Bot before editing user configuration file\."
    edit = False
    user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
    if not get_binance_trade_bot_process():
        if os.path.exists(user_cfg_file_path):
            with open(user_cfg_file_path) as f:
                message = (
                    f"Current configuration file is:\n\n"
                    f"```\n"
                    f"{f.read()}\n"
                    f"```\n\n"
                    f"_*Please reply with a message containing the updated configuration*_.\n\n"
                    f"Write /stop to stop editing and exit without changes.".replace(
                        ".", "\."
                    )
                )
                edit = True
        else:
            message = f"❌ Unable to find user configuration file at `{user_cfg_file_path}`.".replace(
                ".", "\."
            )
    return [message, edit]
Exemplo n.º 5
0
def get_custom_scripts_keyboard():
    logger.info("Getting list of custom scripts.")

    custom_scripts_path = "./config/custom_scripts.json"
    keyboard = []
    custom_script_exist = False
    message = "No custom script was found inside *BTB\-manager\-telegram*'s `/config/custom_scripts.json` file\."

    if os.path.exists(custom_scripts_path):
        with open(custom_scripts_path) as f:
            scripts = json.load(f)
            for script_name in scripts:
                keyboard.append([script_name])

        if len(keyboard) >= 1:
            custom_script_exist = True
            message = "Select one of your custom scripts to execute it\."
    else:
        logger.warning(
            "Unable to find custom_scripts.json file inside BTB-manager-telegram's config/ directory."
        )
        message = "Unable to find `custom_scripts.json` file inside *BTB\-manager\-telegram*'s `config/` directory\."

    keyboard.append(["Cancel"])
    return keyboard, custom_script_exist, message
Exemplo n.º 6
0
def edit_coin(update: Update, _: CallbackContext) -> int:
    logger.info(f"Editing coin list. ({update.message.text})")

    if update.message.text != "/stop":
        message = (f"✔ Successfully edited coin list file to:\n\n"
                   f"```\n"
                   f"{update.message.text}\n"
                   f"```".replace(".", "\."))
        coin_file_path = os.path.join(settings.ROOT_PATH,
                                      "supported_coin_list")
        try:
            copyfile(coin_file_path, f"{coin_file_path}.backup")
            with open(coin_file_path, "w") as f:
                f.write(update.message.text + "\n")
        except Exception:
            message = "❌ Unable to edit coin list file\."
    else:
        message = "👌 Exited without changes\.\nYour `supported_coin_list` file was *not* modified\."

    keyboard = [["Go back"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    update.message.reply_text(message,
                              reply_markup=reply_markup,
                              parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 7
0
def check_status():
    logger.info("Check status button pressed.")

    message = "⚠ Binance Trade Bot is not running."
    if get_binance_trade_bot_process():
        message = "✔ Binance Trade Bot is running."
    return message
Exemplo n.º 8
0
def update_tg_bot(update: Update, _: CallbackContext) -> int:
    logger.info(f"Updating BTB Manager Telegram. ({update.message.text})")

    if update.message.text != "Cancel update":
        message = ("The bot is updating\.\n"
                   "Wait a few seconds then start the bot again with /start")
        keyboard = [["/start"]]
        reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")
        try:
            subprocess.call(
                f"git pull && $(which python3) -m pip install -r requirements.txt --upgrade && "
                f'$(which python3) -m btb_manager_telegram -p "{settings.ROOT_PATH}" &',
                shell=True,
            )
            kill_btb_manager_telegram_process()
        except Exception as e:
            logger.error(f"❌ Unable to update BTB Manager Telegram: {e}")
            message = "Unable to update BTB Manager Telegram"
            update.message.reply_text(message,
                                      reply_markup=reply_markup,
                                      parse_mode="MarkdownV2")
    else:
        message = ("👌 Exited without changes\.\n"
                   "BTB Manager Telegram was *not* updated\.")
        keyboard = [["OK 👌"]]
        reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
        update.message.reply_text(message,
                                  reply_markup=reply_markup,
                                  parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 9
0
def delete_db(update: Update, _: CallbackContext) -> int:
    logger.info(
        f"Asking if the user really wants to delete the db. ({update.message.text})"
    )

    if update.message.text != "Go back":
        message = "✔ Successfully deleted database file\."
        db_file_path = os.path.join(settings.ROOT_PATH,
                                    "data/crypto_trading.db")
        log_file_path = os.path.join(settings.ROOT_PATH,
                                     "logs/crypto_trading.log")
        try:
            copyfile(db_file_path, f"{db_file_path}.backup")
            os.remove(db_file_path)
        except Exception as e:
            logger.error(f"❌ Unable to delete database file: {e}")
            message = "❌ Unable to delete database file\."
        try:
            with open(log_file_path, "w") as f:
                f.truncate()
        except Exception as e:
            logger.error(f"❌ Unable to clear log file: {e}")
            message = "❌ Unable to clear log file\."

    else:
        message = "👌 Exited without changes\.\n" "Your database was *not* deleted\."

    keyboard = [["OK"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)
    update.message.reply_text(message,
                              reply_markup=reply_markup,
                              parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 10
0
def cancel(update: Update, _: CallbackContext) -> int:
    logger.info("Conversation canceled.")

    update.message.reply_text(
        "Bye! I hope we can talk again some day.",
        reply_markup=ReplyKeyboardRemove(),
    )
    return ConversationHandler.END
Exemplo n.º 11
0
def kill_btb_manager_telegram_process():
    try:
        btb_manager_telegram_pid = os.getpid()
        btb_manager_telegram_process = psutil.Process(btb_manager_telegram_pid)
        btb_manager_telegram_process.kill()
        btb_manager_telegram_process.wait()
    except Exception as e:
        logger.info(f"ERROR: {e}")
Exemplo n.º 12
0
def check_progress():
    logger.info("Progress button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get progress information
            try:
                cur.execute(
                    """SELECT th1.alt_coin_id AS coin, th1.alt_trade_amount AS amount, th1.crypto_trade_amount AS priceInUSD,(th1.alt_trade_amount - ( SELECT th2.alt_trade_amount FROM trade_history th2 WHERE th2.state = 'COMPLETE' AND th2.alt_coin_id = th1.alt_coin_id AND th1.datetime > th2.datetime AND th2.selling = 0 ORDER BY th2.datetime DESC LIMIT 1)) AS change, (SELECT th2.datetime FROM trade_history th2 WHERE th2.state = 'COMPLETE' AND th2.alt_coin_id = th1.alt_coin_id AND th1.datetime > th2.datetime AND th2.selling = 0 ORDER BY th2.datetime DESC LIMIT 1) AS pre_last_trade_date, datetime FROM trade_history th1 WHERE th1.state = 'COMPLETE' AND th1.selling = 0 ORDER BY th1.datetime DESC LIMIT 15"""
                )
                query = cur.fetchall()

                # Generate message
                m_list = ["Current coin amount progress:\n\n"]
                for coin in query:
                    last_trade_date = datetime.strptime(
                        coin[5], "%Y-%m-%d %H:%M:%S.%f")
                    if coin[4] is None:
                        pre_last_trade_date = datetime.strptime(
                            coin[5], "%Y-%m-%d %H:%M:%S.%f")
                    else:
                        pre_last_trade_date = datetime.strptime(
                            coin[4], "%Y-%m-%d %H:%M:%S.%f")

                    time_passed = last_trade_date - pre_last_trade_date
                    last_trade_date = last_trade_date.strftime(
                        "%H:%M:%S %d/%m/%Y")
                    m_list.append(
                        f"*{coin[0]}*\n"
                        f"\t\- Amount: `{format_float(coin[1])}` *{coin[0]}*\n"
                        f"\t\- Price: `{round(coin[2]*0.71, 2)}` *GBP*\n"
                        f"\t\- Price: `{round(coin[2], 2)}` *USD*\n"
                        f"\t\- Change: {f'`{format_float(coin[3])}` *{coin[0]}* `{round(coin[3] / (coin[1] - coin[3]) * 100, 2)}` *%* in {time_passed.days} days, {time_passed.seconds // 3600} hours' if coin[3] is not None else f'`{coin[3]}`'}\n"
                        f"\t\- Trade datetime: `{last_trade_date}`\n\n".
                        replace(".", "\."))

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Unable to fetch progress information from database: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Unable to fetch progress information from database\."
                ]
        except Exception as e:
            logger.error(f"❌ Unable to perform actions on the database: {e}",
                         exc_info=True)
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 13
0
def update_reminder(self, message):
    logger.info(f"Reminding user: {message}")

    bot = Bot(settings.TOKEN)
    bot.send_message(settings.CHAT_ID, message, parse_mode="MarkdownV2")
    scheduler.enter(
        60 * 60 * 12,
        1,
        update_reminder,
    )
Exemplo n.º 14
0
def next_coin():
    logger.info("Next coin button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            # Get bridge currency symbol
            with open(user_cfg_file_path) as cfg:
                config = ConfigParser()
                config.read_file(cfg)
                bridge = config.get("binance_user_config", "bridge")
                scout_multiplier = config.get("binance_user_config",
                                              "scout_multiplier")

            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get prices and percentages for a jump to the next coin
            try:
                cur.execute(
                    f"""SELECT p.to_coin_id as other_coin, sh.other_coin_price, (current_coin_price - 0.001 * '{scout_multiplier}' * current_coin_price) / sh.target_ratio AS 'price_needs_to_drop_to', ((current_coin_price - 0.001 * '{scout_multiplier}' * current_coin_price) / sh.target_ratio) / sh.other_coin_price as 'percentage' FROM scout_history sh JOIN pairs p ON p.id = sh.pair_id WHERE p.from_coin_id = (SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1) ORDER BY sh.datetime DESC, percentage DESC LIMIT (SELECT count(DISTINCT pairs.to_coin_id) FROM pairs JOIN coins ON coins.symbol = pairs.to_coin_id WHERE coins.enabled = 1 AND pairs.from_coin_id=(SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1));"""
                )
                query = cur.fetchall()

                m_list = []
                for coin in query:
                    percentage = round(coin[3] * 100, 2)
                    m_list.append(
                        f"*{coin[0]} \(`{format_float(percentage)}`%\)*\n"
                        f"\t\- Current Price: `{format_float(round(coin[1], 8))}` {bridge}\n"
                        f"\t\- Target Price: `{format_float(round(coin[2], 8))}` {bridge}\n\n"
                        .replace(".", "\."))

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Something went wrong, unable to generate next coin at this time: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Something went wrong, unable to generate next coin at this time\.",
                    "⚠ Please make sure logging for _Binance Trade Bot_ is enabled\.",
                ]
        except Exception as e:
            logger.error(f"❌ Unable to perform actions on the database: {e}",
                         exc_info=True)
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 15
0
def stop_bot():
    logger.info("Stop bot button pressed.")

    message = "⚠ Binance Trade Bot is not running."
    if get_binance_trade_bot_process():
        find_and_kill_binance_trade_bot_process()
        if not get_binance_trade_bot_process():
            message = "✔ Successfully stopped the bot."
        else:
            message = (
                "❌ Unable to stop Binance Trade Bot.\n\n"
                "If you are running the telegram bot on Windows make sure to run with administrator privileges."
            )
    return message
Exemplo n.º 16
0
def export_db():
    logger.info("Export database button pressed.")

    message = "⚠ Please stop Binance Trade Bot before exporting the database file\."
    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    fil = None
    if not get_binance_trade_bot_process():
        if os.path.exists(db_file_path):
            with open(db_file_path, "rb") as db:
                fil = db.read()
            message = "Here is your database file:"
        else:
            message = "❌ Unable to Export the database file\."
    return [message, fil]
Exemplo n.º 17
0
def read_log():
    logger.info("Read log button pressed.")

    log_file_path = os.path.join(settings.ROOT_PATH, "logs/crypto_trading.log")
    message = f"❌ Unable to find log file at `{log_file_path}`.".replace(
        ".", "\.")
    if os.path.exists(log_file_path):
        with open(log_file_path) as f:
            file_content = f.read().replace(".", "\.")[-4000:]
            message = (f"Last *4000* characters in log file:\n\n"
                       f"```\n"
                       f"{file_content}\n"
                       f"```")
    return message
Exemplo n.º 18
0
def update_btb():
    logger.info("⬆ Update Binance Trade Bot button pressed.")

    message = "Your Binance Trade Bot installation is already up to date\."
    upd = False
    to_update = is_btb_bot_update_available()
    if to_update is not None:
        if to_update:
            upd = True
            message = ("An update for Binance Trade Bot is available\.\n"
                       "Would you like to update now?")
    else:
        message = "Error while trying to fetch Binance Trade Bot version information\."
    return [message, upd]
Exemplo n.º 19
0
def delete_db():
    logger.info("Delete database button pressed.")

    message = "⚠ Please stop Binance Trade Bot before deleting the database file\."
    delete = False
    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    if not get_binance_trade_bot_process():
        if os.path.exists(db_file_path):
            message = "Are you sure you want to delete the database file?"
            delete = True
        else:
            message = f"⚠ Unable to find database file at `{db_file_path}`.".replace(
                ".", "\."
            )
    return [message, delete]
Exemplo n.º 20
0
def update_tg_bot():
    logger.info("⬆ Update Telegram Bot button pressed.")

    message = "Your BTB Manager Telegram installation is already up to date\."
    upd = False
    to_update = is_tg_bot_update_available()
    if to_update is not None:
        if to_update:
            message = ("An update for BTB Manager Telegram is available\.\n"
                       "Would you like to update now?")
            upd = True
    else:
        message = (
            "Error while trying to fetch BTB Manager Telegram version information\."
        )
    return [message, upd]
Exemplo n.º 21
0
def trade_history():
    logger.info("Trade history button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get last 10 trades
            try:
                cur.execute(
                    """SELECT alt_coin_id, crypto_coin_id, selling, state, alt_trade_amount, crypto_trade_amount, datetime FROM trade_history ORDER BY datetime DESC LIMIT 10;"""
                )
                query = cur.fetchall()

                m_list = [
                    f"Last **{10 if len(query) > 10 else len(query)}** trades:\n\n"
                ]
                for trade in query:
                    if trade[4] is None:
                        continue
                    date = datetime.strptime(trade[6], "%Y-%m-%d %H:%M:%S.%f")
                    m_list.append(
                        f"`{date.strftime('%H:%M:%S %d/%m/%Y')}`\n"
                        f"*{'Sold' if trade[2] else 'Bought'}* `{format_float(trade[4])}` *{trade[0]}*{f' for `{format_float(trade[5])}` *{trade[1]}*' if trade[5] is not None else ''}\n"
                        f"Status: _*{trade[3]}*_\n\n".replace(".", "\.")
                    )

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception as e:
                logger.error(
                    f"❌ Something went wrong, unable to generate trade history at this time: {e}",
                    exc_info=True,
                )
                con.close()
                return [
                    "❌ Something went wrong, unable to generate trade history at this time\."
                ]
        except Exception as e:
            logger.error(
                f"❌ Unable to perform actions on the database: {e}", exc_info=True
            )
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 22
0
def execute_custom_script(update: Update, _: CallbackContext) -> int:
    logger.info(f"Going to 🤖 execute custom script. ({update.message.text})")

    keyboard = [["OK 👌"]]
    reply_markup = ReplyKeyboardMarkup(keyboard, resize_keyboard=True)

    custom_scripts_path = "./config/custom_scripts.json"
    if update.message.text != "Cancel":
        with open(custom_scripts_path) as f:
            scripts = json.load(f)

            try:
                command = ["bash", "-c", str(scripts[update.message.text])]
            except Exception as e:
                logger.error(
                    f"Unable to find script named {update.message.text} in custom_scripts.json file: {e}",
                    exc_info=True,
                )
                message = f"Unable to find script named `{escape_markdown(update.message.text, version=2)}` in `custom_scripts.json` file\."
                update.message.reply_text(message,
                                          reply_markup=reply_markup,
                                          parse_mode="MarkdownV2")

            try:
                proc = subprocess.Popen(
                    command,
                    stdout=subprocess.PIPE,
                )
                output, _ = proc.communicate()
                message_list = telegram_text_truncator(
                    escape_markdown(output.decode("utf-8"), version=2),
                    padding_chars_head="```\n",
                    padding_chars_tail="```",
                )
                for message in message_list:
                    update.message.reply_text(message,
                                              reply_markup=reply_markup,
                                              parse_mode="MarkdownV2")
            except Exception as e:
                logger.error(f"Error during script execution: {e}",
                             exc_info=True)
                message = "Error during script execution\."
                update.message.reply_text(message,
                                          reply_markup=reply_markup,
                                          parse_mode="MarkdownV2")

    return MENU
Exemplo n.º 23
0
def start_bot():
    logger.info("Start bot button pressed.")

    message = "⚠ Binance Trade Bot is already running\."
    if not get_binance_trade_bot_process():
        if os.path.exists(os.path.join(settings.ROOT_PATH, "binance_trade_bot/")):
            subprocess.call(
                f"cd {settings.ROOT_PATH} && $(which python3) -m binance_trade_bot &",
                shell=True,
            )
            if get_binance_trade_bot_process():
                message = "✔ Binance Trade Bot successfully started\."
            else:
                message = "❌ Unable to start Binance Trade Bot\."
        else:
            message = (
                f"❌ Unable to find _Binance Trade Bot_ installation at {settings.ROOT_PATH}\.\n"
                f"Make sure the `binance-trade-bot` and `BTB-manager-telegram` are in the same parent directory\."
            )
    return message
Exemplo n.º 24
0
def edit_coin():
    logger.info("Edit coin list button pressed.")

    message = "⚠ Please stop Binance Trade Bot before editing the coin list\."
    edit = False
    coin_file_path = os.path.join(settings.ROOT_PATH, "supported_coin_list")
    if not get_binance_trade_bot_process():
        if os.path.exists(coin_file_path):
            with open(coin_file_path) as f:
                message = (
                    f"Current coin list is:\n\n"
                    f"```\n{f.read()}\n```\n\n"
                    f"_*Please reply with a message containing the updated coin list*_.\n\n"
                    f"Write /stop to stop editing and exit without changes.".
                    replace(".", "\."))
                edit = True
        else:
            message = f"❌ Unable to find coin list file at `{coin_file_path}`.".replace(
                ".", "\.")
    return [message, edit]
Exemplo n.º 25
0
def start(update: Update, _: CallbackContext) -> int:
    logger.info("Started conversation.")

    keyboard = [["Begin"]]
    message = (
        f"Hi *{escape_markdown(update.message.from_user.first_name)}*\!\n"
        f"Welcome to _Binace Trade Bot Manager Telegram_\.\n\n"
        f"This Telegram bot was developed by @lorcalhost\.\n"
        f"Find out more about the project [here](https://github.com/lorcalhost/BTB-manager-telegram)\.\n\n"
        f"If you like the bot please [consider supporting the project 🍻](https://www.buymeacoffee.com/lorcalhost)\."
    )
    reply_markup = ReplyKeyboardMarkup(keyboard,
                                       one_time_keyboard=True,
                                       resize_keyboard=True)
    update.message.reply_text(
        message,
        reply_markup=reply_markup,
        parse_mode="MarkdownV2",
        disable_web_page_preview=True,
    )
    return MENU
Exemplo n.º 26
0
def setup_telegram_constants():
    logger.info("Retrieving Telegram token and chat_id from apprise.yml file.")
    telegram_url = None
    yaml_file_path = os.path.join(settings.ROOT_PATH, "config/apprise.yml")
    if os.path.exists(yaml_file_path):
        with open(yaml_file_path) as f:
            try:
                parsed_urls = yaml.load(f, Loader=yaml.FullLoader)["urls"]
            except Exception:
                logger.error(
                    "Unable to correctly read apprise.yml file. Make sure it is correctly set up. Aborting."
                )
                exit(-1)
            for url in parsed_urls:
                if url.startswith("tgram"):
                    telegram_url = url.split("//")[1]
        if not telegram_url:
            logger.error(
                "No telegram configuration was found in your apprise.yml file. Aborting."
            )
            exit(-1)
    else:
        logger.error(
            f'Unable to find apprise.yml file at "{yaml_file_path}". Aborting.'
        )
        exit(-1)
    try:
        settings.TOKEN = telegram_url.split("/")[0]
        settings.CHAT_ID = telegram_url.split("/")[1]
        logger.info(
            f"Successfully retrieved Telegram configuration. "
            f"The bot will only respond to user in the chat with chat_id {settings.CHAT_ID}"
        )
    except Exception:
        logger.error(
            "No chat_id has been set in the yaml configuration, anyone would be able to control your bot. Aborting."
        )
        exit(-1)
Exemplo n.º 27
0
def update_checker():
    logger.info("Checking for updates.")

    if settings.TG_UPDATE_BROADCASTED_BEFORE is False:
        if is_tg_bot_update_available():
            logger.info("BTB Manager Telegram update found.")

            message = (
                "âš  An update for _BTB Manager Telegram_ is available\.\n\n"
                "Please update by going to *🛠 Maintenance* and pressing the *⬆ Update Telegram Bot* button\."
            )
            settings.TG_UPDATE_BROADCASTED_BEFORE = True
            bot = Bot(settings.TOKEN)
            bot.send_message(settings.CHAT_ID,
                             message,
                             parse_mode="MarkdownV2")
            sleep(1)
            bot.close()
            sleep(1)
            scheduler.enter(
                60 * 60 * 12,
                1,
                update_reminder,
                ("_*Reminder*_:\n\n" + message, ),
            )

    if settings.BTB_UPDATE_BROADCASTED_BEFORE is False:
        if is_btb_bot_update_available():
            logger.info("Binance Trade Bot update found.")

            message = (
                "âš  An update for _Binance Trade Bot_ is available\.\n\n"
                "Please update by going to *🛠 Maintenance* and pressing the *Update Binance Trade Bot* button\."
            )
            settings.BTB_UPDATE_BROADCASTED_BEFORE = True
            bot = Bot(settings.TOKEN)
            bot.send_message(settings.CHAT_ID,
                             message,
                             parse_mode="MarkdownV2")
            sleep(1)
            bot.close()
            sleep(1)
            scheduler.enter(
                60 * 60 * 12,
                1,
                update_reminder,
                ("_*Reminder*_:\n\n" + message, ),
            )

    if (settings.TG_UPDATE_BROADCASTED_BEFORE is False
            or settings.BTB_UPDATE_BROADCASTED_BEFORE is False):
        sleep(1)
        scheduler.enter(
            60 * 60,
            1,
            update_checker,
        )
Exemplo n.º 28
0
def current_ratios():
    logger.info("Current ratios button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    user_cfg_file_path = os.path.join(settings.ROOT_PATH, "user.cfg")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            # Get bridge currency symbol
            with open(user_cfg_file_path) as cfg:
                config = ConfigParser()
                config.read_file(cfg)
                bridge = config.get("binance_user_config", "bridge")

            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get current coin symbol
            try:
                cur.execute(
                    """SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1;"""
                )
                current_coin = cur.fetchone()[0]
                if current_coin is None:
                    raise Exception()
            except Exception:
                con.close()
                return ["❌ Unable to fetch current coin from database\."]

            # Get prices and ratios of all alt coins
            try:
                cur.execute(
                    f"""SELECT sh.datetime, p.to_coin_id, sh.other_coin_price, ( ( ( current_coin_price / other_coin_price ) - 0.001 * 5 * ( current_coin_price / other_coin_price ) ) - sh.target_ratio ) AS 'ratio_dict' FROM scout_history sh JOIN pairs p ON p.id = sh.pair_id WHERE p.from_coin_id='{current_coin}' AND p.from_coin_id = ( SELECT alt_coin_id FROM trade_history ORDER BY datetime DESC LIMIT 1) ORDER BY sh.datetime DESC LIMIT ( SELECT count(DISTINCT pairs.to_coin_id) FROM pairs WHERE pairs.from_coin_id='{current_coin}');"""
                )
                query = cur.fetchall()

                # Generate message
                last_update = datetime.strptime(query[0][0], "%Y-%m-%d %H:%M:%S.%f")
                query = sorted(query, key=lambda k: k[-1], reverse=True)

                m_list = [
                    f"\nLast update: `{last_update.strftime('%H:%M:%S %d/%m/%Y')}`\n\n"
                    f"*Coin ratios compared to {current_coin}:*\n".replace(".", "\.")
                ]
                for coin in query:
                    m_list.append(
                        f"*{coin[1]}*:\n"
                        f"\t\- Price: `{coin[2]}` {bridge}\n"
                        f"\t\- Ratio: `{round(coin[3], 6)}`\n\n".replace(".", "\.")
                    )

                message = telegram_text_truncator(m_list)
                con.close()
            except Exception:
                con.close()
                return [
                    "❌ Something went wrong, unable to generate ratios at this time\.",
                    "⚠ Please make sure logging for _Binance Trade Bot_ is enabled\.",
                ]
        except Exception:
            message = ["❌ Unable to perform actions on the database\."]
    return message
Exemplo n.º 29
0
def setup_root_path_constant():
    if settings.ROOT_PATH is None:
        logger.info("No root_path was specified. Aborting.")
        exit(-1)
    else:
        settings.ROOT_PATH = os.path.join(settings.ROOT_PATH, "")
Exemplo n.º 30
0
def current_value():
    logger.info("Current value button pressed.")

    db_file_path = os.path.join(settings.ROOT_PATH, "data/crypto_trading.db")
    message = [f"⚠ Unable to find database file at `{db_file_path}`\."]
    if os.path.exists(db_file_path):
        try:
            con = sqlite3.connect(db_file_path)
            cur = con.cursor()

            # Get current coin symbol, bridge symbol, order state, order size, initial buying price
            try:
                cur.execute(
                    """SELECT alt_coin_id, crypto_coin_id, state, alt_trade_amount, crypto_starting_balance, crypto_trade_amount FROM trade_history ORDER BY datetime DESC LIMIT 1;"""
                )
                (
                    current_coin,
                    bridge,
                    state,
                    alt_amount,
                    order_size,
                    buy_price,
                ) = cur.fetchone()
                if current_coin is None:
                    raise Exception()
                if state == "ORDERED":
                    return [
                        f"A buy order of `{round(order_size, 2)}` *{bridge}* is currently placed on coin *{current_coin}*.\n\n"
                        f"_Waiting for buy order to complete_.".replace(".", "\.")
                    ]
            except Exception:
                con.close()
                return ["❌ Unable to fetch current coin from database\."]

            # Get balance, current coin price in USD, current coin price in BTC
            try:
                cur.execute(
                    f"""SELECT balance, usd_price, btc_price, datetime FROM 'coin_value' WHERE coin_id = '{current_coin}' ORDER BY datetime DESC LIMIT 1;"""
                )
                query = cur.fetchone()
                if query is None:
                    return [
                        f"❌ No information about *{current_coin}* available in the database\.",
                        "⚠ If you tried using the `Current value` button during a trade please try again after the trade has been completed\.",
                    ]
                balance, usd_price, btc_price, last_update = query
                if balance is None:
                    balance = 0
                if usd_price is None:
                    usd_price = 0
                if btc_price is None:
                    btc_price = 0
                last_update = datetime.strptime(last_update, "%Y-%m-%d %H:%M:%S.%f")
            except Exception:
                con.close()
                return [
                    "❌ Unable to fetch current coin information from database\.",
                    "⚠ If you tried using the `Current value` button during a trade please try again after the trade has been completed\.",
                ]

            # Generate message
            try:
                m_list = [
                    f"\nLast update: `{last_update.strftime('%H:%M:%S %d/%m/%Y')}`\n\n"
                    f"*Current coin {current_coin}:*\n"
                    f"\t\- Balance: `{round(balance, 6)}` *{current_coin}*\n"
                    f"\t\- Current coin exchange ratio: `{round(usd_price, 6)}` *USD*/*{current_coin}*\n"
                    f"\t\- Value in *USD*: `{round((balance * usd_price), 2)}` *USD*\n"
                    f"\t\- Value in *BTC*: `{round((balance * btc_price), 6)}` *BTC*\n\n"
                    f"_Initially bought for_ {round(buy_price, 2)} *{bridge}*\n"
                    f"_Exchange ratio when purchased:_ `{round((buy_price / alt_amount), 6)}` *{bridge}*/*{current_coin}*".replace(
                        ".", "\."
                    )
                ]
                message = telegram_text_truncator(m_list)
                con.close()
            except Exception:
                con.close()
                return [
                    "❌ Something went wrong, unable to generate value at this time\."
                ]
        except Exception:
            message = ["❌ Unable to perform actions on the database\."]
    return message