Esempio n. 1
0
    def get_agenda(self, horizon_incoming, horizon_unfinished,
                   list_unfinished_appointments, relative_to):
        "Generate agenda in a text format"

        log.info("Getting agenda from %r to %r", horizon_unfinished,
                 horizon_incoming)

        # Open and read when needed so the file can be updated
        # without restarting bot.
        template = helpers.get_template(self.agenda_path, self.agenda_content)

        since = relative_to.replace(hour=0, minute=0)
        if (relative_to - since).total_seconds() < 4 * 60 * 60:
            # Include more past
            since -= dt.timedelta(hours=4)

        ctx = {
            # TODO: planned
            'planned': [],
            'unfinished':
            self.get_unfinished(horizon_unfinished,
                                list_unfinished_appointments, relative_to),
            # Incoming - from the whole day
            'appointments':
            self.get_appointments(since=since, horizon=horizon_incoming),
            'now':
            relative_to,
        }

        return template.render(ctx)
Esempio n. 2
0
    def refresh_events(self):
        """
        Read events from exchange, convert and update calendar.
        """
        log.info("Periodic operation executed")

        now = self.time.now()

        start_of_day = now.replace(hour=0, minute=0)
        horizon_end = now + dt.timedelta(hours=self.horizon_incoming)

        try:
            events = self.exch_calendar.list_events(start=start_of_day,
                                                    end=horizon_end,
                                                    details=True)
        except AttributeError:
            # Module is badly written. In case of connection errors it
            # throws Attribute Error. Show error in case something weird
            # happened, but don't kill bot.
            log.exception("Connection (probably) error within exch module.")
            return None

        calendar_events = []
        for event in events.events:
            converted = self.convert_event(event)
            calendar_events.append(converted)

        log.info('Read %d events from exchange', len(calendar_events))

        # Use shared state to talk to core plugins
        self.state['calendar'].update_events(calendar_events, 'exch')
        return calendar_events
Esempio n. 3
0
    def refresh_db(self):
        "Refresh/load DB with org entries"
        log.info('Refreshed/read org-mode data')
        db = helpers.load_orgnode(self.parsed_config)
        events = [
            helpers.orgnode_to_event(node, self.parsed_config) for node in db
        ]

        self.state['calendar'].update_events(events, 'org')
        return events
Esempio n. 4
0
    def initialize(self):
        """
        Called third, after all plugins are registered. Use it to initialize the
        plugin.

        It's a good place to register periodic callbacks using self.scheduler.
        You can also use other plugins public API via the self.state object.
        """
        log.info("3. Initialize the plugin")

        # There might be some operation you need to do periodically:
        self.scheduler.every(30).seconds.do(self.periodic)
Esempio n. 5
0
    def register(self):
        """
        Called second: Use this method to register any commands/callbacks via the
        self.assistant API.
        """
        log.info("2. Register plugin commands")

        # You can register some commands here
        commands = [
            (['owa_refresh'], self.handle_refresh),
        ]
        for aliases, callback in commands:
            self.assistant.command.register(aliases, callback)
Esempio n. 6
0
    def validate_config(self):
        """
        Called first: Use this method to read config parameters and substitute
        defaults were appropriate.

        You should touch all your config variables here so we can inform the
        user if he have mistyped something in the config file (even when --test
        parameter is given)

        Available API: self.config, self.assistant, self.scheduler.
        self.state might not be fully populated and ready yet.
        """
        log.info("1. Validate and read config")
        self.parameter = self.config.get('parameter',
                                         assert_type=int,
                                         default=42)
Esempio n. 7
0
    def schedule_notifications(self):
        "Schedule incoming notifications"

        # Program may hang for indefinite amount of time and we still should
        # not miss any notifications. At the same time calendar may get updated,
        # tasks added or removed. We can't send duplicates.

        # Prepare incoming notifications up to 5 minutes before
        window_size = 5

        now = self.time.now()

        for notify_period in self.notify_periods:
            # Calculate window
            wnd_start = now + dt.timedelta(minutes=notify_period)
            wnd_end = wnd_start + dt.timedelta(minutes=window_size)
            wnd_start = max(wnd_start, self.notify_positions[notify_period])

            last_scheduled = wnd_start
            for event in self.calendar.events:
                # Ignore date-less events
                if event.relevant_date is None:
                    continue

                date = event.relevant_date.sort_date
                # We want to schedule an event if it lies between now+notify_period and
                # now+notify_period+prepare_before

                if not event.relevant_date.appointment:
                    continue

                if date <= wnd_start:
                    continue
                if date > wnd_end:
                    continue

                log.info("Scheduling %dm notification for event %r",
                         notify_period, event)
                delta = (date -
                         self.time.now()).total_seconds() - notify_period * 60
                self.scheduler.every(delta).seconds.do(self.send_notice, event)
                last_scheduled = max(last_scheduled, date)

            self.notify_positions[notify_period] = last_scheduled
Esempio n. 8
0
    def _initialize_plugins(self):
        "Create instances of plugins"
        # {name: handler1, name2: handler1, name3: handler2, ...}
        plugins = self.config.get('plugins', assert_type=dict)
        for plugin_name, plugin_config in plugins.items():
            plugin_cls = Assistant.registered_plugins.get(plugin_name, None)
            if plugin_cls is None:
                raise ConfigError("Configured plugin '%s' is not registered" %
                                  plugin_name)

            plugin = plugin_cls(self, plugin_config, self.scheduler, self.time,
                                self.state)
            plugin.validate_config()
            plugin.register()
            self.plugins[plugin_name] = plugin
            log.info('Plugin %s instantiated', plugin_name)

        # After all plugins are created - initialize plugins
        for plugin in self.plugins.values():
            plugin.initialize()
Esempio n. 9
0
    def periodic(self):
        "Example: Periodic operations"
        log.info("Periodic operation executed")

        # Use shared state to talk to core plugins
        self.state['calendar'].add_events([], 'owa')