From 383a7a4eda1d8ea39ef31bbcd64e57040f85ac83 Mon Sep 17 00:00:00 2001 From: Guillaume De Saint Martin Date: Mon, 7 Oct 2024 14:34:54 +0200 Subject: [PATCH] [Community] add clear_local_data_if_necessary --- octobot/cli.py | 1 + octobot/community/authentication.py | 32 ++++++++++++++++++++++++++++- octobot/constants.py | 1 + 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/octobot/cli.py b/octobot/cli.py index 8bf7f162f..48f9fdad5 100644 --- a/octobot/cli.py +++ b/octobot/cli.py @@ -194,6 +194,7 @@ async def _get_authenticated_community_if_possible(config, logger): # switch environments if necessary octobot_community.IdentifiersProvider.use_environment_from_config(config) community_auth = octobot_community.CommunityAuthentication.create(config) + community_auth.clear_local_data_if_necessary() try: if not community_auth.is_initialized(): if constants.IS_CLOUD_ENV: diff --git a/octobot/community/authentication.py b/octobot/community/authentication.py index 36a3868c7..416bab4d4 100644 --- a/octobot/community/authentication.py +++ b/octobot/community/authentication.py @@ -18,6 +18,8 @@ import json import time import typing +import hashlib +import os import octobot.constants as constants import octobot.enums as enums @@ -528,17 +530,39 @@ def remove_login_detail(self): self.save_tradingview_email("") self.logger.debug("Removed community login data") - def clear_bot_scoped_config(self): + def _clear_bot_scoped_config(self): """ Clears all bot local data including mqtt id, which will trigger a new mqtt device creation. Warning: should only be called in rare cases, mostly to avoid multi connection on the same mqtt device """ + self.logger.info( + "Clearing bot local scoped config data. Your TradingView alert email address " + "and webhook url will be different on this bot." + ) self._save_bot_id("") self.save_tradingview_email("") # also reset mqtt id to force a new mqtt id creation self._save_mqtt_device_uuid("") + def clear_local_data_if_necessary(self): + if constants.IS_CLOUD_ENV: + # disabled on cloud environments + return + previous_local_identifier = self._get_saved_bot_scoped_data_identifier() + current_local_identifier = self._get_bot_scoped_data_identifier() + if not previous_local_identifier: + self._save_bot_scoped_data_identifier(current_local_identifier) + # nothing to clear + return + if current_local_identifier != previous_local_identifier: + self._clear_bot_scoped_config() + self._save_bot_scoped_data_identifier(current_local_identifier) + + def _get_bot_scoped_data_identifier(self) -> str: + # identifier is based on the path to the local bot to ensure the same data are not re-used + # when copy/pasting a bot config to another bot + return hashlib.sha256(os.getcwd().encode()).hexdigest() async def stop(self): self.logger.debug("Stopping ...") @@ -723,6 +747,9 @@ def save_tradingview_email(self, tradingview_email: str): def _save_mqtt_device_uuid(self, mqtt_uuid: str): self._save_value_in_config(constants.CONFIG_COMMUNITY_MQTT_UUID, mqtt_uuid) + def _save_bot_scoped_data_identifier(self, identifier: str): + self._save_value_in_config(constants.CONFIG_COMMUNITY_LOCAL_DATA_IDENTIFIER, identifier) + def get_saved_package_urls(self) -> list[str]: return self._get_value_in_config(constants.CONFIG_COMMUNITY_PACKAGE_URLS) or [] @@ -731,6 +758,9 @@ def get_saved_mqtt_device_uuid(self) -> str: return mqtt_uuid raise errors.NoBotDeviceError("No MQTT device ID has been set") + def _get_saved_bot_scoped_data_identifier(self) -> str: + return self._get_value_in_config(constants.CONFIG_COMMUNITY_LOCAL_DATA_IDENTIFIER) + def get_saved_tradingview_email(self) -> str: return self._get_value_in_config(constants.CONFIG_COMMUNITY_TRADINGVIEW_EMAIL) diff --git a/octobot/constants.py b/octobot/constants.py index 896e811c7..f7c666285 100644 --- a/octobot/constants.py +++ b/octobot/constants.py @@ -106,6 +106,7 @@ CONFIG_COMMUNITY_TRADINGVIEW_EMAIL = "tradingview_email" CONFIG_COMMUNITY_PACKAGE_URLS = "package_urls" CONFIG_COMMUNITY_ENVIRONMENT = "environment" +CONFIG_COMMUNITY_LOCAL_DATA_IDENTIFIER = "local_data_identifier" USE_BETA_EARLY_ACCESS = os_util.parse_boolean_environment_var("USE_BETA_EARLY_ACCESS", "false") USER_ACCOUNT_EMAIL = os.getenv("USER_ACCOUNT_EMAIL", "") USER_PASSWORD_TOKEN = os.getenv("USER_PASSWORD_TOKEN", None)