From 412cea45a9a4be40990348be06ba51fe05e61322 Mon Sep 17 00:00:00 2001 From: Alex Yao Date: Thu, 25 Aug 2016 14:58:28 -0700 Subject: [PATCH] Live config update --- configs/config.json.cluster.example | 4 +++ configs/config.json.example | 4 +++ configs/config.json.map.example | 4 +++ configs/config.json.optimizer.example | 4 +++ configs/config.json.path.example | 4 +++ configs/config.json.pokemon.example | 4 +++ docs/configuration_files.md | 2 ++ pokecli.py | 46 ++++++++++++++++++++++----- 8 files changed, 64 insertions(+), 8 deletions(-) diff --git a/configs/config.json.cluster.example b/configs/config.json.cluster.example index 32067c3520..f7a050c5e6 100644 --- a/configs/config.json.cluster.example +++ b/configs/config.json.cluster.example @@ -11,6 +11,10 @@ "websocket_server": false, "heartbeat_threshold": 10, "enable_social": true, + "live_config_update": { + "enabled": false, + "tasks_only": false + }, "tasks": [ { "//NOTE: This task MUST be placed on the top of task list": {}, diff --git a/configs/config.json.example b/configs/config.json.example index be08aa7a67..4ac3c413d0 100644 --- a/configs/config.json.example +++ b/configs/config.json.example @@ -11,6 +11,10 @@ "websocket_server": false, "heartbeat_threshold": 10, "enable_social": true, + "live_config_update": { + "enabled": false, + "tasks_only": false + }, "tasks": [ { "//NOTE: This task MUST be placed on the top of task list": {}, diff --git a/configs/config.json.map.example b/configs/config.json.map.example index 9717fca52c..4ae087f2ee 100644 --- a/configs/config.json.map.example +++ b/configs/config.json.map.example @@ -11,6 +11,10 @@ "websocket_server": false, "heartbeat_threshold": 10, "enable_social": true, + "live_config_update": { + "enabled": false, + "tasks_only": false + }, "tasks": [ { "//NOTE: This task MUST be placed on the top of task list": {}, diff --git a/configs/config.json.optimizer.example b/configs/config.json.optimizer.example index 315d3bdba2..dcccbb048e 100644 --- a/configs/config.json.optimizer.example +++ b/configs/config.json.optimizer.example @@ -11,6 +11,10 @@ "websocket_server": false, "heartbeat_threshold": 10, "enable_social": true, + "live_config_update": { + "enabled": false, + "tasks_only": false + }, "tasks": [ { "//NOTE: This task MUST be placed on the top of task list": {}, diff --git a/configs/config.json.path.example b/configs/config.json.path.example index 305964113d..c5567c5cd3 100644 --- a/configs/config.json.path.example +++ b/configs/config.json.path.example @@ -11,6 +11,10 @@ "websocket_server": false, "heartbeat_threshold": 10, "enable_social": true, + "live_config_update": { + "enabled": false, + "tasks_only": false + }, "tasks": [ { "//NOTE: This task MUST be placed on the top of task list": {}, diff --git a/configs/config.json.pokemon.example b/configs/config.json.pokemon.example index 51793fe2bf..a40da1c9ea 100644 --- a/configs/config.json.pokemon.example +++ b/configs/config.json.pokemon.example @@ -11,6 +11,10 @@ "websocket_server": false, "heartbeat_threshold": 10, "enable_social": true, + "live_config_update": { + "enabled": false, + "tasks_only": false + }, "tasks": [ { "//NOTE: This task MUST be placed on the top of task list": {}, diff --git a/docs/configuration_files.md b/docs/configuration_files.md index a17af0550d..db42d08576 100644 --- a/docs/configuration_files.md +++ b/docs/configuration_files.md @@ -81,6 +81,8 @@ Document the configuration options of PokemonGo-Bot. |`pokemon_bag.show_count` | false | Show amount of each pokemon. |`pokemon_bag.pokemon_info` | [] | Check any config example file to see available settings. |`favorite_locations` | [] | Allows you to define a collection of locations and coordinates, allowing rapid switch using a "label" on your location config +| `live_config_update.enabled` | false | Enable live config update +| `live_config_update.tasks_only` | false | True: quick update for Tasks only (without re-login). False: slower update for entire config file. ## Configuring Tasks diff --git a/pokecli.py b/pokecli.py index 3930a082db..5983e33e74 100644 --- a/pokecli.py +++ b/pokecli.py @@ -74,6 +74,18 @@ def handle_sigint(*args): raise SIGINTRecieved signal.signal(signal.SIGINT, handle_sigint) + def initialize_task(bot, config): + tree = TreeConfigBuilder(bot, config.raw_tasks).build() + bot.workers = tree + + def initialize(config): + bot = PokemonGoBot(config) + bot.start() + initialize_task(bot,config) + bot.metrics.capture_stats() + bot.health_record = BotEvent(config) + return bot + def get_commit_hash(): try: hash = subprocess.check_output(['git', 'rev-parse', 'HEAD'], stderr=subprocess.STDOUT)[:-1] @@ -88,7 +100,7 @@ def get_commit_hash(): sys.stdout = codecs.getwriter('utf8')(sys.stdout) sys.stderr = codecs.getwriter('utf8')(sys.stderr) - config = init_config() + config, config_file = init_config() if not config: return @@ -100,12 +112,8 @@ def get_commit_hash(): while not finished: try: - bot = PokemonGoBot(config) - bot.start() - tree = TreeConfigBuilder(bot, config.raw_tasks).build() - bot.workers = tree - bot.metrics.capture_stats() - bot.health_record = health_record + bot = initialize(config) + config_changed = check_mod(config_file) bot.event_manager.emit( 'bot_start', @@ -116,6 +124,12 @@ def get_commit_hash(): while True: bot.tick() + if config.live_config_update_enabled and config_changed(): + logger.info('Config changed! Applying new config.') + config, _ = init_config() + + if config.live_config_update_tasks_only: initialize_task(bot, config) + else: bot = initialize(config) except KeyboardInterrupt: bot.event_manager.emit( @@ -212,6 +226,18 @@ def get_commit_hash(): data={'path': cached_forts_path} ) +def check_mod(config_file): + check_mod.mtime = os.path.getmtime(config_file) + + def compare_mtime(): + mdate = os.path.getmtime(config_file) + if check_mod.mtime == mdate: # mtime didnt change + return False + else: + check_mod.mtime = mdate + return True + + return compare_mtime def report_summary(bot): if bot.metrics.start_time is None: @@ -265,6 +291,7 @@ def _json_loader(filename): if config_arg and os.path.isfile(config_arg): _json_loader(config_arg) + config_file = config_arg elif os.path.isfile(config_file): logger.info('No config argument specified, checking for /configs/config.json') _json_loader(config_file) @@ -596,6 +623,9 @@ def _json_loader(filename): config.daily_catch_limit = load.get('daily_catch_limit', 800) config.vips = load.get('vips', {}) config.sleep_schedule = load.get('sleep_schedule', []) + config.live_config_update = load.get('live_config_update', {}) + config.live_config_update_enabled = config.live_config_update.get('enabled', False) + config.live_config_update_tasks_only = config.live_config_update.get('tasks_only', False) if config.map_object_cache_time < 0.0: parser.error("--map_object_cache_time is out of range! (should be >= 0.0)") @@ -662,7 +692,7 @@ def task_configuration_error(flag_name): raise fix_nested_config(config) - return config + return config, config_file def add_config(parser, json_config, short_flag=None, long_flag=None, **kwargs): if not long_flag: