示例#1
0
    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
示例#2
0
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