diff --git a/pokecli.py b/pokecli.py index 23d726d1c5..d46a28d327 100644 --- a/pokecli.py +++ b/pokecli.py @@ -144,7 +144,7 @@ def setup_logging(config): handler.setFormatter(formatter) def start_bot(bot, config): - bot.start() + bot.start(bot) initialize_task(bot, config) bot.metrics.capture_stats() bot.health_record = BotEvent(config) diff --git a/pokemongo_bot/__init__.py b/pokemongo_bot/__init__.py index 769b61f47d..a451840039 100644 --- a/pokemongo_bot/__init__.py +++ b/pokemongo_bot/__init__.py @@ -158,8 +158,8 @@ def __init__(self, db, config): saved_info[key] = self.config.client_id saved_info.close() - def start(self): - self._setup_event_system() + def start(self, bot): + self._setup_event_system(bot) self.sleep_schedule = SleepSchedule(self, self.config.sleep_schedule) if self.config.sleep_schedule else None if self.sleep_schedule: self.sleep_schedule.work() @@ -174,7 +174,7 @@ def start(self): random.seed() - def _setup_event_system(self): + def _setup_event_system(self, bot): handlers = [] color = self.config.logging and 'color' in self.config.logging and self.config.logging['color'] @@ -199,7 +199,7 @@ def _setup_event_system(self): remote_control = WebsocketRemoteControl(self).start() # @var EventManager - self.event_manager = EventManager(self.config.walker_limit_output, *handlers) + self.event_manager = EventManager(bot, self.config.walker_limit_output, *handlers) self._register_events() if self.config.show_events: self.event_manager.event_report() diff --git a/pokemongo_bot/event_manager.py b/pokemongo_bot/event_manager.py index 2be9f02f66..1902a5790f 100644 --- a/pokemongo_bot/event_manager.py +++ b/pokemongo_bot/event_manager.py @@ -3,6 +3,18 @@ from __future__ import print_function from sys import stdout +from datetime import datetime, timedelta +import time +import json +import os + + +from pokemongo_bot.base_dir import _base_dir + + +class FileIOException(Exception): + pass + class EventNotRegisteredException(Exception): pass @@ -20,15 +32,129 @@ def __init__(self): def handle_event(self, event, kwargs): raise NotImplementedError("Please implement") - + +class Event(object): + """ + Representation of an event. + """ + def __init__(self, event, sender=None, level='info', formatted='', data={}): + """ + Representation of an Event + :return: An Event + :rtype: Event + """ + t = datetime.today() + self.timestamp = t.strftime('%Y-%m-%d %H:%M:%S') + self.event = str(event).encode('ascii', 'xmlcharrefreplace') + if sender==None: + self.sender = sender + else: + self.sender = str(sender).encode('ascii', 'xmlcharrefreplace') + + self.level = str(level).encode('ascii', 'xmlcharrefreplace') + self.formatted = str(formatted).encode('ascii', 'xmlcharrefreplace') + self.data = str(data).encode('ascii', 'xmlcharrefreplace') + self.friendly_msg = "" + + if not formatted: + self.friendly_msg = self.data + else: + #Format the data + self.friendly_msg = formatted.format(**data) + + def __str__(self): + return self.timestamp + ": [" + str(self.event) + "] " + str(self.data) + + +class Events(object): + def __init__(self, bot): + self._events = [] + self.MaxEventlog = 50 + self.bot = bot + if bot==None: + self._username = "TESTBUILD" + else: + self._username = self.bot.config.username + #Hardcoded to avoid the file is being flooded on disk + self._write_debug = False + + def retrieve_data(self): + return self._events + + def get(self, number): + return self._events[number] + + def all(self): + return list(self._data.values()) + + def remove_event_by_num(self, number): + del self._events[number] + + + def add_event(self, event): + #Do not log anything on disk when in Jenkins test build + if self._username == "TESTBUILD": + return + + if event.level=="debug" and self._write_debug==False: + return + else: + self._events.append(event) + #Check if we exceed the max log entries + if len(self._events) > self.MaxEventlog: + self.remove_event_by_num(0) + #Write file to disk + self.update_web_event() + + def init_event_outfile(self): + web_event = os.path.join(_base_dir, "web", "events-%s.json" % self._username) + + if not os.path.exists(web_event): + self.bot.logger.info('No events file %s found. Creating a new one' % web_event) + + json_events = [] + + with open(web_event, "w") as outfile: + json.dump(json_events, outfile) + + def update_web_event(self): + web_event = os.path.join(_base_dir, "web", "events-%s.json" % self._username) + + if not os.path.exists(web_event): + self.init_event_outfile() + + json_events = self.jsonify_events() + #self.bot.logger.info('####### Writing %s' % json_events) + + try: + with open(web_event, "w") as outfile: + json.dump(json_events, outfile) + except (IOError, ValueError) as e: + self.bot.logger.info('[x] Error while opening events file for write: %s' % e, 'red') + except: + raise FileIOException("Unexpected error writing to {}".web_event) + + def jsonify_events(self): + json_events = [] + for event in self._events: + json_events.append({"event": {"timestamp": event.timestamp, "friendly_msg": event.friendly_msg, "event": event.event, "level": event.level, "formatted": event.formatted, "data": event.data}}) + return json_events + + class EventManager(object): - def __init__(self, limit_output=False, *handlers): + def __init__(self, bot ,limit_output=False, *handlers): + + self._registered_events = dict() self._handlers = list(handlers) or [] self._last_event = None self._limit_output = limit_output + self.bot = bot + self._EventLog = Events(self.bot) + + def event_report(self): for event, parameters in self._registered_events.iteritems(): print('-'*80) @@ -75,3 +201,7 @@ def emit(self, event, sender=None, level='info', formatted='', data={}): # send off to the handlers for handler in self._handlers: handler.handle_event(event, sender, level, formatted_msg, data) + + #Log the event in the event_log + l_event = Event(event, sender, level, formatted, data) + self._EventLog.add_event(l_event) diff --git a/tests/__init__.py b/tests/__init__.py index 17f4615145..83fc28695e 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -34,8 +34,8 @@ class FakeBot(PokemonGoBot): def __init__(self): self.config = MagicMock(websocket_server_url=False, show_events=False) self.api = FakeApi() - self.event_manager = EventManager() - self._setup_event_system() + self.event_manager = EventManager(None) + self._setup_event_system(None) def updateConfig(self, conf): self.config.__dict__.update(conf)