Exemplo n.º 1
0
 def __init__(self, *args, **kwargs):
     super(LunchBot, self).__init__(*args, **kwargs)
     self.weather = WeatherForecast()
     self.schedule.every().day.at("11:55").do(self.eat_some)
     self.schedule.every().day.at("15:55").do(self.eat_some)
     self.announce_ts = None
     self.ask_for_reply_after = None
     self.users_to_ask = []
Exemplo n.º 2
0
class LunchBot(ChatBot):
    ASK_TIMEOUT = 15
    EXCLUDE = {
        "sobolevi": (datetime.datetime(2016, 5, 17), datetime.datetime(2016, 6, 1)),
        "mikhailzakharov": (datetime.datetime(2010, 1, 1), datetime.datetime(2020, 1, 1)),
        "deminp": (datetime.datetime(2016, 7, 14), datetime.datetime(2016, 7, 25)),
        "ivanchen": (datetime.datetime(2016, 7, 11), datetime.datetime(2016, 7, 25)),
    }

    def __init__(self, *args, **kwargs):
        super(LunchBot, self).__init__(*args, **kwargs)
        self.weather = WeatherForecast()
        self.schedule.every().day.at("11:55").do(self.eat_some)
        self.schedule.every().day.at("15:55").do(self.eat_some)
        self.announce_ts = None
        self.ask_for_reply_after = None
        self.users_to_ask = []

    @trigger
    def on_weather(self):
        return self.weather.report()

    @every_minute
    @weekday
    def on_timeout(self):
        if self.ask_for_reply_after is not None:
            delta = round((time.time() - self.ask_for_reply_after) / 60)
            disable = False
            if 0 <= delta < self.ASK_TIMEOUT:
                disable = self.ask_for_reply()
            if delta > self.ASK_TIMEOUT:
                logger.debug("Asking for reply timeout - %d - cancelling", delta)
                disable = True
            if disable:
                self.ask_for_reply_after = None
                self.users_to_ask = []

    @weekday
    def eat_some(self):
        response = self.broker.post(
            "Who is going to eat? Beware, it's {0}".format(self.weather.report()),
            color='warning',
        )
        logger.debug('Posted %r', response)
        self.announce_ts = float(response['message']['ts'])
        self.ask_for_reply_after = self.announce_ts + 60 * 3
        self.users_to_ask = self.dont_mention(self.users_on_channel())
        logger.debug('Scheduling ask_for_reply for %r after %r',
                     self.users_to_ask, self.ask_for_reply_after)

    def dont_mention(self, users):
        now = datetime.datetime.now()
        to_keep = set()
        for username in users.values():
            if username in self.EXCLUDE:
                if self.EXCLUDE[username][0] <= now < self.EXCLUDE[username][1]:
                    continue
            to_keep.add(username)
        return {k: v
                for k, v in users.items()
                if v in to_keep}

    def users_on_channel(self):
        return {user_id: self.username(user_id)
                for user_id in self.broker.channel_info(self.broker.CHANNEL_NAME)['members']
                if user_id != self.broker.MY_ID}

    def ask_for_reply(self):
        """
        Check if not all chatroom participants replied
        Ask for reply if found any.
        """
        logger.debug("Asking for reply")
        # Bot messages do not have 'user' field
        replied_user_ids = {x.get('user') for x in self.broker.read_new_messages(self.announce_ts)}
        logger.debug("Users replied after announcement: %r", replied_user_ids)
        if replied_user_ids.intersection(self.users_to_ask):
            # At least one user replied
            to_ask = set(self.users_to_ask).difference(replied_user_ids)
            if to_ask:
                for user_id in to_ask:
                    logger.debug("Asking %r", self.users_to_ask[user_id])
                    self.broker.post('@{0}, are you going to eat some?'.format(self.users_to_ask[user_id]))
                logger.debug('Looks like one reminder is enough... Canceling join')
            else:
                logger.debug('Everyone replied, canceling')
            return True
        logger.debug('Do not be first to reply to yourself, skipping')
        return False