diff --git a/src/CoindroidAPI.py b/src/CoindroidAPI.py index 4637c4d..db23f99 100644 --- a/src/CoindroidAPI.py +++ b/src/CoindroidAPI.py @@ -5,8 +5,10 @@ from gevent import Greenlet class CoindroidAPITask(Greenlet): def __init__(self, **kwargs): Greenlet.__init__(self) - self.eventsEvent = kwargs.get("eventsEvent") - self.eventsEvent.clear() + self.eventTaskEvent = kwargs.get("eventTaskEvent") + self.droidControllerQueue = kwargs.get("droidControllerQueue") + if self.eventTaskEvent: + self.eventTaskEvent.clear() self.logger = logging.getLogger(self.__class__.__name__) self.apiSession = requests.Session() self.lastTransaction = None diff --git a/src/Currency.py b/src/Currency.py index 631ff75..f06e4e4 100644 --- a/src/Currency.py +++ b/src/Currency.py @@ -10,8 +10,8 @@ class CurrencyTask(CoindroidAPITask): self.logger = logging.getLogger(self.__class__.__name__) self.currencyComparisonTuple = namedtuple("currencyComparison", ["added", "removed", "modified", "same"]) + self.eventTaskEvent.set() self.updateCurrency() - self.eventsEvent.set() def dictCompare(self, d1, d2): d1_keys = set(d1.keys()) @@ -88,9 +88,11 @@ class CurrencyTask(CoindroidAPITask): while True: update = self.compareCurrency() if update: - self.eventsEvent.set() + self.eventTaskEvent.set() + self.logger.debug("Sleeping...") sleep(self.pause) else: + self.logger.debug("Sleeping...") sleep(self.pause) self.logger.debug("Updating currency...") self.updateCurrency() diff --git a/src/Droid.py b/src/Droid.py index 8d932bb..9052f10 100644 --- a/src/Droid.py +++ b/src/Droid.py @@ -1,92 +1,85 @@ import logging from CoindroidAPI import CoindroidAPITask from gevent import sleep +from collections import namedtuple +from twilio.rest import Client as TwilioClient -# todo Flesh out getting events to Droids and having them act accordingly -class DroidTask(CoindroidAPITask): +class DroidControllerTask(CoindroidAPITask): def __init__(self, **kwargs): - """ - This is a DroidTask - It performs actions on events received from:w - - :param \**kwargs: - See below - :Keyword Arguments: - * *apiUrl* (``str``) -- - Coindroids API URL. - Default is ``https://api.coindroids.com/`` - * *pause* (``int``) -- - Time to wait between requests - """ - super(EventTask, self).__init__(**kwargs) - self.logger = logging.getLogger(__name__) - self.updateEvents() + super(DroidControllerTask, self).__init__(**kwargs) + self.logger = logging.getLogger(self.__class__.__name__) + self.droidTuple = namedtuple("droidTuple", + ["block_height", "action_id", "action_type", "player_id", "player_username", + "droid_id", "droid_name", "targetID", "targetName", "healthChangedFrom", + "healthChangedTo", "netDamageTaken", "experienceEarned", "grossDamagePerformed", + "experienceChangedFrom", "experienceChangedTo", + ]) + twilioAccount = "ACdfcd2b529db83954e8a0041796072960" + twilioToken = "ab9b98a0b3da8a728d14774192773af2" + self.twilioClient = TwilioClient(twilioAccount, twilioToken) - def updateEvents(self): - while True: - try: - request = self.apiSession.get(self.apiUrl + "event", - params={"order" : "block_height.desc", - "currency_id": "eq.2"}) - # "involved_droids": ""}).json() - except: - self.logger.exception("Unable to get events!") - self.logger.error("Waiting for update...") - sleep(self.pause) - continue - self.currentTransaction = request.json() - self.logger.info("Retrieved events from Coindroids...") - self.logger.debug("{} events found...".format(len(self.currentTransaction))) - if not self.lastTransaction: - self.logger.info("No previous events available... Waiting for update...") - self.lastTransaction = self.currentTransaction.copy() - self.currentTransaction = None - sleep(self.pause) - continue - break + def getDroidStats(self, event): + return { + "block_height" : event.get("block_height"), + "action_id" : event.get("action_id"), + "action_type" : event.get("action_type"), + "player_id" : event.get("player_id"), + "player_username" : event.get("player_username"), + "droid_id" : event.get("droid_id"), + "droid_name" : event.get("droid_name"), + "targetID" : event.get("target").get("id"), + "targetName" : event.get("target").get("name"), + "healthChangedFrom" : next( + (x.get("value_from") for x in event.get("outcomes") if x.get("outcome_type") == "Health changed"), + None), + "healthChangedTo" : next( + (x.get("value_to") for x in event.get("outcomes") if x.get("outcome_type") == "Health changed"), + None), + "netDamageTaken" : next( + (x.get("value_to") for x in event.get("outcomes") if x.get("outcome_type") == "Net damage taken"), + None), + "experienceEarned" : next( + (x.get("value_to") for x in event.get("outcomes") if x.get("outcome_type") == "Experience earned"), + None), + "grossDamagePerformed" : next((x.get("value_to") for x in event.get("outcomes") if + x.get("outcome_type") == "Gross damage performed"), None), + "experienceChangedFrom": next((x.get("value_from") for x in event.get("outcomes") if + x.get("outcome_type") == "Experience changed"), None), + "experienceChangedTo" : next( + (x.get("value_to") for x in event.get("outcomes") if x.get("outcome_type") == "Experience changed"), + None) + } - def compareEvents(self): - """ - Compares old events to new events - :return: list of events - """ - setLastEventsIDs = set([x.get("action_id") for x in self.lastTransaction]) - setEventsIDs = set([x.get("action_id") for x in self.currentTransaction]) - setRemovedEvents = setLastEventsIDs - setEventsIDs - setAddedEvents = setEventsIDs - setLastEventsIDs - ret = [] - if setRemovedEvents: - self.logger.debug("Events removed from this update: {}".format(setRemovedEvents)) - if setAddedEvents: - self.logger.debug("Added events:") - for event_id in setAddedEvents: - for event in self.currentTransaction: - if event: - if event["action_id"] == event_id: - ret.append(event) - self.logger.debug("At block_height {}, action_id {} - {}({}):{}({}) did {} on {}".format( - *(event.get(i) for i in ("block_height", - "action_id", "player_username", "player_id", - "droid_name", "droidID", "action_type", - "target")))) - else: - self.logger.error("Found empty event!") - return ret + def sendSMS(self, from_="+14159037708", **kwargs): + try: + self.twilioClient.messages.create(from_=from_, **kwargs) + except: + self.logger.exception("Unable to send SMS!!") + pass def _run(self): self.logger.info("Running {}".format(self.__class__.__name__)) while True: - if self.eventsEvent.ready(): + if not self.droidControllerQueue.empty(): self.logger.debug("{} woken up...".format(self.__class__.__name__)) - for _ in range(5): - self.logger.debug("Trying to get updated events ({}/5)".format(_)) - update = self.compareEvents() - if update: - self.logger.debug("TODO: Send events to queue for worker threads") - break + events = self.droidControllerQueue.get() + for event in events: + stats = self.getDroidStats(event) + message = "At block_height {block_height}, action_id {action_id} - " \ + "{player_username}({player_id}):{droid_name}({droid_id}) did {action_type} on " \ + "{targetName}({targetID}). Health changed from {healthChangedFrom} to " \ + "{healthChangedTo}.".format(**stats) + self.logger.info(message) + if stats["targetID"] or stats["targetName"]: + if (stats["targetID"] == 160) or (stats["targetName"] == "bob"): + self.logger.debug("bob's got an action!!! sending sms!!") + self.sendSMS(to="+14088963912", body=message) + if (stats["targetID"] == 165) or (stats["targetName"] == "Mabuhay"): + self.logger.debug("bob's got an action!!! sending sms!!") + self.sendSMS(to="+14088963912", body=message) else: - self.logger.debug("No events detected") - sleep(5) + self.logger.warning("Event has no target!") + else: + self.logger.debug("Queue is empty... No action to take...") sleep(self.pause) - continue diff --git a/src/Event.py b/src/Event.py index 86ed163..493e5a1 100644 --- a/src/Event.py +++ b/src/Event.py @@ -1,16 +1,12 @@ import logging from CoindroidAPI import CoindroidAPITask from gevent import sleep -from twilio.rest import Client as TwilioClient class EventTask(CoindroidAPITask): def __init__(self, **kwargs): super(EventTask, self).__init__(**kwargs) self.logger = logging.getLogger(self.__class__.__name__) - twilioAccount = "ACdfcd2b529db83954e8a0041796072960" - twilioToken = "ab9b98a0b3da8a728d14774192773af2" - self.twilioClient = TwilioClient(twilioAccount, twilioToken) self.updateEvents() def updateEvents(self, updateLast=True): @@ -47,45 +43,12 @@ class EventTask(CoindroidAPITask): setAddedEvents = setEventsIDs - setLastEventsIDs ret = [] if setAddedEvents: - self.logger.debug("Added events:") + self.logger.debug("Events have been added...") for event_id in setAddedEvents: for event in self.currentTransaction: if event: if event["action_id"] == event_id: ret.append(event) - keys = ["block_height", "action_id", "player_username", "player_id", "droid_name", - "droid_id", "action_type"] - message_args = [event.get(i) for i in keys] - if event.get("target"): - message_args.extend([event["target"].get("name"), event["target"].get("id")]) - if (event["target"].get("name") == "bob") or (event["target"].get("id") == 160): - self.logger.debug("TEMP - bob's got an action!!! sending sms!!") - try: - self.twilioClient.messages.create( - to="+14088963912", - from_="+14159037708", - body="At block_height {}, action_id {} - {}({}):{}({}) did {} on {}({})".format( - *message_args) - ) - except: - self.logger.exception("Unable to send SMS!!") - if (event["target"].get("name") == "Mabuhay") or (event["target"].get("id") == 165): - self.logger.debug("TEMP - Mabuhay's got an action!!! sending sms!!") - try: - self.twilioClient.messages.create( - to="+14086342295", - from_="+14159037708", - body="At block_height {}, action_id {} - {}({}):{}({}) did {} on {}({})".format( - *message_args) - ) - except: - self.logger.exception("Unable to send SMS!!") - else: - self.logger.warning("Event has no target!") - message_args.extend([None, None]) - self.logger.debug( - "At block_height {}, action_id {} - {}({}):{}({}) did {} on {}({})".format( - *message_args)) else: self.logger.error("Found empty event!") return ret @@ -93,22 +56,26 @@ class EventTask(CoindroidAPITask): def _run(self): self.logger.info("Running {}".format(self.__class__.__name__)) while True: - if self.eventsEvent.ready(): + if self.eventTaskEvent.ready(): self.logger.debug("{} woken up...".format(self.__class__.__name__)) for _ in range(5): self.logger.debug("Trying to get updated events ({}/5)".format(_)) self.updateEvents(updateLast=False) update = self.compareEvents() if update: - self.eventsEvent.clear() - self.logger.debug("TODO: Send events to queue for worker threads") + self.eventTaskEvent.clear() self.updateEvents() + self.logger.debug("Sending events to queue for DroidTasks") + self.droidControllerQueue.put(update) break else: self.logger.debug("No events detected") + self.logger.debug("Sleeping...") sleep(5) self.updateEvents(updateLast=False) else: self.logger.error("No events detected after 5 rounds!") + self.eventTaskEvent.clear() + self.logger.debug("Sleeping...") sleep(self.pause) continue diff --git a/src/main.py b/src/main.py index 6fc5ef5..28212d6 100644 --- a/src/main.py +++ b/src/main.py @@ -4,8 +4,10 @@ import gevent, logging from gevent.event import Event +from gevent.queue import Queue from Currency import CurrencyTask from Event import EventTask +from Droid import DroidControllerTask formatter = logging.Formatter('%(asctime)s - %(name)s %(funcName)s():%(lineno)d - %(levelname)s - %(message)s') logger = logging.getLogger() @@ -20,11 +22,14 @@ def main(): logger = logging.getLogger(__name__) while True: logger.info("Starting main loop...") - eventsEvent = Event() - currencyTask = CurrencyTask.spawn(eventsEvent=eventsEvent) - eventTask = EventTask.spawn(eventsEvent=eventsEvent) - gevent.joinall([currencyTask, eventsEvent]) + eventTaskEvent = Event() + droidControllerQueue = Queue() + currencyTask = CurrencyTask.spawn(eventTaskEvent=eventTaskEvent) + eventTask = EventTask.spawn(eventTaskEvent=eventTaskEvent, droidControllerQueue=droidControllerQueue) + droidController = DroidControllerTask.spawn(droidControllerQueue=droidControllerQueue) + gevent.joinall([currencyTask, eventTask, droidController]) logger.error("Main loop ended... This shouldn't happen?") + if __name__ == "__main__": main()