def __init__(self): self.interval = 5.0 self.running = False self.configParser = ConfigParser.RawConfigParser() self.configParser.read('config/dob.cfg') self.data_manager = DataManager(configParser=self.configParser) self.drive_watcher = GDriveWatcher(configParser=self.configParser, data_manager=self.data_manager) self.slack_bot = SlackBot(configParser=self.configParser) self.witmanager = WitAIManager(configParser=self.configParser) self.last_drive_scan = None
class DOBService(object): def __init__(self): self.interval = 5.0 self.running = False self.configParser = ConfigParser.RawConfigParser() self.configParser.read('config/dob.cfg') self.data_manager = DataManager(configParser=self.configParser) self.drive_watcher = GDriveWatcher(configParser=self.configParser, data_manager=self.data_manager) self.slack_bot = SlackBot(configParser=self.configParser) self.witmanager = WitAIManager(configParser=self.configParser) self.last_drive_scan = None def start(self): if self.running: return logging.info('Service starting') self.setup() self.running = True # self.thread = threading.Thread(target=self.run, args=()) # self.thread.daemon = True # self.thread.start() self.run() def setup(self): self.data_manager.connect() self.drive_watcher.connect() self.slack_bot.connect() def run(self): while self.running: now = datetime.datetime.now() # get updated files if self.last_drive_scan is None or ((now - self.last_drive_scan).seconds * 0.0166667) >= 30: self.last_drive_scan = now updated_files = self.drive_watcher.update() self.broadcast_updated_files(updated_files) self.process_slack_messages() time.sleep(self.interval) def process_slack_messages(self): packets = self.slack_bot.update() for packet in packets: event_type = packet['type'] #if event_type == 'hello': #elif event_type == 'message': # self.process_slack_message(packet['message']) #elif event_type == 'user_typing': # #elif event_type == 'team_join': # #elif event_type == 'presence_change': # #else: # if event_type == 'message': self.process_slack_message(packet) def process_slack_message(self, packet): if packet is None or len(packet) == 0: return logging.info('Processing message {}'.format(packet)) if not self.is_valid_slack_message(packet): return user = self.slack_bot.users[packet['user']] channel = self.slack_bot.channels[self.slack_bot.get_channel_key_for_channel_with_id(packet['channel'])] text = packet['text'] if text is None or len(text) == 0: return import re matches = re.findall ('<@[a-zA-z0-9]*>:', text, re.DOTALL) idx = 0 for match in matches: #if ":" in match: if idx == 0: text = text.replace(match, "") else: user_id = match.replace("<", "").replace(">", "").replace("@", "").replace(":", "").strip() user = None if user_id in self.slack_bot.users: user = self.slack_bot.users[user_id] if user is not None: #text = text.replace(match, user['emailAddress']) text = text.replace(match, user['name']) else: text = text.replace(match, "") idx += 1 status, outcomes = self.witmanager.query(text) if outcomes is None or len(outcomes) == 0: return outcome = outcomes[0] # TODO: check that the first always has the highest confience value logging.info('Message has intent {}'.format(outcome.intent)) if outcome.intent == WitAIOutcome.INTENT_RETRIEVE_FILES: self.process_intent_to_retrieve_files(user, channel, outcome) def process_intent_to_retrieve_files(self, user, channel, outcome): min_date = None max_date = None contacts = [] for entity in outcome.entities: if entity.type == WitAIEntity.TYPE_CONTACT: if entity.value is None or len(entity.value) == 0: continue contacts.append(entity.value.lower()) elif entity.type == WitAIEntity.TYPE_DATE: cur_date = entity.value_to_date() if cur_date is not None: if min_date is None and max_date is None: min_date = cur_date max_date = cur_date else: if min_date > cur_date: min_date = cur_date if max_date < cur_date: max_date = cur_date # query db entities = self.data_manager.search_files(contacts=contacts, min_date=min_date, max_date=max_date) if entities is None or len(entities) == 0: msg = "@{} cannot find any files based on your search terms".format(user['name']) self.slack_bot.send_message(msg, channel=channel['id']) else: #msgs = [] msg = "here are some files matching your query:" for entity in entities: if entity.mimeType == GMimeType.Folder: continue #msgs.append("{} ({})".format(entity.title, entity.get_link())) msg += "\n" link = entity.get_link() if link is None or len(link) == 0: msg += "{}".format(entity.title) else: msg += "{} ({})".format(entity.title, entity.get_link()) #for msg in msgs: # self.slack_bot.send_message(msg, channel=channel['id']) self.slack_bot.send_message(msg, channel=channel['id']) def is_valid_slack_message(self, message): if 'channel' not in message: return False if 'text' not in message: return False channel = message['channel'] text = message['text'] mentions = DOBService.extract_entities_from_text(text) return self.slack_bot.me['user_id'] in mentions and channel == self.slack_bot.channels[self.slack_bot.channel]['id'] @staticmethod def extract_entities_from_text(text): import re return re.findall('<@(.*?)>', text, re.DOTALL) def broadcast_updated_files(self, updated_files): print "broadcast_updated_files; updated/added count {}".format(len(updated_files)) for entity in updated_files: msgs = self.construct_slack_message_for_entity(entity) for msg in msgs: self.slack_bot.send_message(msg) def construct_slack_message_for_entities(self, updated_files): now = datetime.datetime.now() updates_dict = {} msgs = [] for entity in updated_files: if (now - entity.modifiedDate).days >= 2: print "ignoring {}".format(entity.title) continue title = entity.title link = entity.get_link() if entity.createdDate == entity.modifiedDate: key = entity.get_owners() else: key = entity.get_modifier() if key not in updates_dict: updates_dict[key] = [] updates_dict[key].append((title, link)) # create messages for key, value in updates_dict.iteritems(): titles = value[0] links = value[1] if len(titles) == 1: msg = "{} updated {} ({})".format(key, titles[0], links[0]) else: msg = "{} has updated " for i in range(len(titles)): if i > 0: msg += ", " msg += titles[i] msg += " ({})".format(links[i]) msgs.append(msg) return msgs def construct_slack_message_for_entity(self, entity): now = datetime.datetime.now() if (now - entity.modifiedDate).days >= 2: print "ignoring {}".format(entity.title) return [] if entity.createdDate == entity.modifiedDate: return ["{} has created a new file {}\n{}".format( entity.get_owners(), entity.title, entity.get_link())] else: return ["{} has modified {}\n{}".format( entity.get_modifier(), entity.title, entity.get_link())] def stop(self): self.running = False