Beispiel #1
0
def is_recurring(event):
    r = RecurringEvent(now_date=datetime.datetime.utcnow())
    try:
        r.parse(event)
        return r.is_recurring
    except ValueError:
        return False
Beispiel #2
0
def parse_frequency(
        frequency: Text) -> Optional[Union[datetime, RecurringEvent]]:
    """
    Parse frequency or date using `recurrent` and `dateparser` module.
    """
    if frequency.startswith("every"):
        rec = RecurringEvent()
        parsed_rrule = rec.parse(frequency)
        if rec.bymonthday or rec.byyearday:
            # not supported
            return None

        try:
            rrulestr(parsed_rrule)  # this validates the parsing
        except (ValueError, TypeError):
            return None
        else:
            # ensure that hours are set, otherwise default to 9am
            if not rec.byhour and not rec.byminute:
                rec.byhour.append("9")
                rec.byminute.append("0")
            return rec
    else:
        value = dateparser.parse(frequency,
                                 settings={"PREFER_DATES_FROM": "future"})
        if value and not value.hour and not value.minute:
            # default 9am if no times
            value = value.replace(hour=9)
        return value
Beispiel #3
0
def recurrent_parse(event):
    r = RecurringEvent(now_date=datetime.datetime.utcnow())
    r.parse(event)
    start_time, success = parse_time(event)
    if success:
        return r, {'start_time':start_time}
    else:
        return r, {}
Beispiel #4
0
    def run(self):
        logging.info('psmqtt using config: %s', self.CONFIG)
        logging.info('you can set the configuration '
                     'with environment variable "PSMQTTCONFIG"')

        clientid = self.cf.get('mqtt_clientid', 'psmqtt-%s' % os.getpid())

        # additonal userdata for mqtt callbacks
        mqttc_userdata = MqttUserdata(
            self.request_topic, self.qos, self.run_task)

        # initialise MQTT broker connection
        mqttc = paho.Client(
            clientid, clean_session=True, userdata=mqttc_userdata)
        self.mqttc = mqttc

        mqttc.on_message = on_message
        mqttc.on_connect = on_connect
        mqttc.on_disconnect = on_disconnect

        mqttc.will_set('clients/psmqtt', payload="Adios!", qos=0, retain=False)

        # Delays will be: 3, 6, 12, 24, 30, 30, ...
        # mqttc.reconnect_delay_set(
        #   delay=3, delay_max=30, exponential_backoff=True)

        mqttc.username_pw_set(self.cf.get('mqtt_username'),
                              self.cf.get('mqtt_password'))

        mqttc.connect(self.cf.get('mqtt_broker', 'localhost'),
                      int(self.cf.get('mqtt_port', '1883')), 60)

        # parse schedule
        schedule = self.cf.get('schedule', {})
        s = sched.scheduler(time.time, time.sleep)
        now = datetime.now()
        for t in schedule:
            r = RecurringEvent()
            dt = r.parse(t)
            if not r.is_recurring:
                logging.error(t + " is not recurring time. Skipping")
                continue
            rrule = rrulestr(dt)
            delay = (rrule.after(now) - now).total_seconds()
            s.enter(delay, 1, self.on_timer, [s, rrule, schedule[t]])

        tt = TimerThread(s)
        tt.daemon = True
        tt.start()
        while True:
            try:
                mqttc.loop_forever()
            except socket.error:
                print('socket error retrying.')
                time.sleep(5)
            except KeyboardInterrupt:
                sys.exit(0)
Beispiel #5
0
    def __init__(self, config):
        self.key, self.config = config.items()[0]

        parser = RecurringEvent(now_date=datetime.now())

        # set attributes
        self.unit = self.config.get("unit", "number")
        self.interval = parser.parse(self.config["interval"])
        self.text = self.config["text"]
Beispiel #6
0
 def __init__(self, start, end):
     """
     :param start: earliest time schedule events may occur, inclusive, and reference time for relative time descriptions
     :param end: latest time schedule events may occur, inclusive
     :return: new `Scheduler` instance
     """
     self.start, self.end = start, end
     self.events = []
     self.recurrent_parser = RecurringEvent(now_date=start)
Beispiel #7
0
    def parse_time_preferences(self, time_ranges_string):
        timeranges = time_ranges_string.split(";")
        parsedranges = []
        dtparser = RecurringEvent()
        for timerange in timeranges:
            [lower, upper] = timerange.split("-")
            lowertime = dtparser.parse(lower)
            uppertime = dtparser.parse(upper)
            parsedranges.append((lowertime.time(), uppertime.time()))

        return sorted(parsedranges, key=lambda x: x[0])
def parse_next_event_from_string(s):
    r = RecurringEvent(now_date=datetime.datetime.now())
    r.parse(s)
    if r.is_recurring:
        rr = rrule.rrulestr(r.get_RFC_rrule())
        return time.mktime(rr.after(datetime.datetime.now()).timetuple())
    else:
        cal = parsedatetime.Calendar()
        if time.mktime(datetime.datetime.now().timetuple()) == time.mktime(
                cal.parse(s)[0]):
            raise Exception("Can't understand this time expression")
        return time.mktime(cal.parse(s)[0])
Beispiel #9
0
def get_dates(frequency, today, end):
    try:
        return [pd.Timestamp(frequency).normalize()]
    except ValueError:
        pass
    try:
        r = RecurringEvent()
        r.parse(frequency)
        rr = rrule.rrulestr(r.get_RFC_rrule())
        return [
            pd.to_datetime(date).normalize()
            for date in rr.between(today, end)
        ]
    except ValueError as e:
        raise ValueError('Invalid Frequecy')
 def next_pickup(self):
     r = RecurringEvent(now_date=datetime.now())
     r.parse(self.pickup_time)
     rr = rrule.rrulestr(r.get_RFC_rrule())
     next_date = rr.after(datetime.now())
     try:
         date_exception = DistrictExceptions.objects.get(date=next_date,
                                                         district=self)
     except:
         date_exception = None
     if date_exception:
         new_date = date_exception.new_date
         if not new_date:
             next_date = rr.after(next_date)
         else:
             next_date = new_date
     return next_date.date()
 def next_pickup(self):
     r = RecurringEvent(now_date=datetime.now())
     r.parse(self.pickup_time)
     rr = rrule.rrulestr(r.get_RFC_rrule())
     next_date = rr.after(datetime.now())
     try:
         date_exception = DistrictExceptions.objects.get(date=next_date,
                                                         district=self)
     except:
         date_exception = None
     if date_exception:
         new_date = date_exception.new_date
         if not new_date:
             next_date = rr.after(next_date)
         else:
             next_date = new_date
     return next_date.date()
Beispiel #12
0
    def insert(self, value):
        ''' A new thought to be inserted, parses thought input and extracts hashtags, people, reminder and location '''
        with shelve.open(self.dbf, writeback=True) as db:
            thought = value

            # Get Location
            location = None
            if ';' in value:
                thought, _, location = value.rpartition(';')
                location = location.strip()
                g = geocoder.google(location)
                if g.latlng is None:
                    print('Trying OSM')
                    g = geocoder.osm(location)
                location = (location, g.latlng)

            # Prase Recurring event
            r = RecurringEvent() # read more here https://github.com/kvh/recurrent
            print(r.parse(thought))

            # Colour Hashtags
            hashtags = {tag for tag in thought.split() if tag.startswith("#")}
            thought = self.highlight_terms(thought, hashtags, 'ffdc00')
            # Colour People
            people = {tag for tag in thought.split() if tag.startswith("@")}
            thought = self.highlight_terms(thought, people, '7fdbff')

            # Create People who don't exist
            for person in people:
                if person not in db:
                    db[person] = Person(person)
                    
            # Cleanup
            value = thought
            if location:
                value += '; ' + location

            # Save Thought to DB
            db['known_terms'] = list(set(db.get('known_terms', []) + list(hashtags) + list(people)))
            t = Thought(value, hashtags, people, r, location)
            db['thoughts'] = db.get('thoughts', [])
            db['thoughts'].insert(0, t)
            # Insert into UI
            self.rv.data.insert(0, {'value': value or 'empty thought'})
Beispiel #13
0
def get_dates(freq, Start, End):
    try:
        return [pd.Timestamp(freq).normalize()]
    except ValueError:
        pass
    try:
        return pd.date_range(start=Start, end=End, freq=freq)
    except ValueError:
        pass
    try:
        r = RecurringEvent()
        r.parse(freq)
        rr = rrule.rrulestr(r.get_RFC_rrule())
        return [
            pd.to_datetime(date).normalize()
            for date in rr.between(Start, End)
        ]
    except ValueError as e:
        raise ValueError('Invalid frequency')
Beispiel #14
0
    def __call__(self, parser, namespace, values, option_string=None):
        if namespace.add is None:
            raise argparse.ArgumentError(self, 'This argument must be provided along with --add. E.g.: --add facebook.com --playtime_days="every weekend"')

        if len(values) != 1:
            raise argparse.ArgumentError(self, 'This argument must be provided only once and contain a single recurrence string. E.g.: --playtime_days="every weekend"')

        play_days = values[0]

        if RecurringEvent().parse(play_days) is None:
            raise argparse.ArgumentError(self, "Invalid recurrence input %s" % play_days)

        if getattr(namespace, self.dest) is not None:
            raise argparse.ArgumentError(self, "--playtime_days can only be provided once")

        setattr(namespace, self.dest, play_days)
Beispiel #15
0
class Scheduler:
    def __init__(self, start, end):
        """
        :param start: earliest time schedule events may occur, inclusive, and reference time for relative time descriptions
        :param end: latest time schedule events may occur, inclusive
        :return: new `Scheduler` instance
        """
        self.start, self.end = start, end
        self.events = []
        self.recurrent_parser = RecurringEvent(now_date=start)

    def register(self, description, data = None):
        """
        Registers an event with the schedule, with a description such as "every feb 2 at noon".

        :param description: English language description of event, which must include a natural language description of when it occurs.
        :param data: arbitrary user data to associate with an event instance
        :return: None
        """
        parsed_rrule = self.recurrent_parser.parse(description)
        assert parsed_rrule is not None, "Could not detect event times from description."
        if isinstance(parsed_rrule, datetime.datetime): # only a single instance of the event, given as a datetime
            self.events.append((parsed_rrule, data))
        else: # RRULE string, find each instance of the event in the current time frame
            assert isinstance(parsed_rrule, str)
            rrule = dateutil.rrule.rrulestr(parsed_rrule)

            # determine the first occurrence of the event, since `rrule.between` below doesn't work if the start time is after the first occurrence
            start = self.start
            if self.recurrent_parser.dtstart is not None:
                start = self.recurrent_parser.dtstart

            for occurrence in rrule.between(start, self.end, inc=True):
                if occurrence >= self.start: # filter out the ones that are before the start time
                    self.events.append((occurrence, data))

    def list_events(self):
        """
        Produces a sorted list of tuples,

        :return: A sorted list of tuples, each containing an event occurrence as a `datetime.datetime` and the event user data.
        """
        return sorted(self.events, key=lambda event: event[0])
Beispiel #16
0
def convert_recurring_event_to_trigger_format(event: RecurringEvent):
    """
    Convert RecurringEvent instances to the APScheduler trigger cron format.

    https://github.com/kvh/recurrent
    https://apscheduler.readthedocs.io/en/stable/modules/triggers/cron.html
    """
    params = event.get_params()
    interval = params.pop("interval")
    frequency_value = "*" if interval == 1 else f"*/{interval}"
    frequency_key = RECURRING_EVENT_FREQUENCY_MAPPING[params.pop("freq")]

    trigger_params = {
        RECURRING_EVENT_PARAMS_MAPPING[param]:
        (_map_weekdays(value) if param == "byday" else value)
        for param, value in params.items()
    }
    trigger_params[frequency_key] = frequency_value
    return trigger_params
Beispiel #17
0
    def do_GET(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/plain')
        self.end_headers()
        query = urlparse(self.path).query
        query_components = dict(qc.split("=") for qc in query.split("&"))
        msg = ' '.join(query_components["message"].split('%20'))
        msg = '\''.join(msg.split('%27'))
        intent = clf.predict([msg])[0]
        if intent == 'create_event':
            r = RecurringEvent(now_date=datetime.now())
            dt = r.parse(msg)
            if "p.m." in msg and dt.hour < 12:
                dt += timedelta(hours=12)
            if "a.m." in msg and dt.hour > 12:
                dt -= timedelta(hours=12)
            reply = random.choice(create_replies)
            event = {
                'summary': 'Meeting',
                'start': {
                    'dateTime': dt.isoformat(),
                    'timeZone': 'America/Denver',
                },
                'end': {
                    'dateTime': (dt + timedelta(hours=1)).isoformat(),
                    'timeZone': 'America/Denver',
                }
            }
            event = service.events().insert(calendarId='primary',
                                            body=event).execute()

        else:  #query_events
            now = datetime.utcnow().isoformat() + 'Z'  # 'Z' indicates UTC time
            reply = 'Your Agenda:<br>'
            eventsResult = service.events().list(
                calendarId='primary',
                timeMin=now,
                maxResults=10,
                singleEvents=True,
                orderBy='startTime').execute()
            events = eventsResult.get('items', [])
            if not events:
                reply = 'No upcoming events found.'
            for event in events:
                start = event['start']
                if start.get('dateTime'):
                    dt = dateutil.parser.parse(start.get('dateTime'))
                    hour = str(
                        dt.hour) if dt.hour <= 12 and dt.hour > 0 else str(
                            abs(dt.hour - 12))
                    minute = str(
                        dt.minute) if dt.minute > 9 else '0' + str(dt.minute)
                    meridiem_indicator = ' AM' if dt.hour < 12 else ' PM'
                    date = dt.date()
                    time = hour + ':' + minute + meridiem_indicator
                else:
                    dt = dateutil.parser.parse(start.get('date'))
                    date = dt.date()
                    time = 'All-Day'
                reply += '<br>' + str(dt.month) + '/' + str(
                    dt.day) + ' ' + time + ' ' + event['summary']
        self.wfile.write({"intent": intent, "reply": reply})
Beispiel #18
0
def one_time_process(date):
    table = str.maketrans("", "", string.punctuation)
    date_string = ' '.join(date).translate(table)
    r = RecurringEvent(now_date=datetime.datetime.utcnow())
    return r.parse(date_string)
Beispiel #19
0
def contains_date(event):
    r = RecurringEvent(now_date=datetime.datetime.utcnow())
    try:
        return r.parse(event) is not None
    except ValueError:
        return False
def is_event_recurring(s):
    r = RecurringEvent(now_date=datetime.datetime.now())
    r.parse(s)
    return r.is_recurring
Beispiel #21
0
def non_recurrent_parse(event):
    r = RecurringEvent(now_date=datetime.datetime.utcnow())
    return r.parse(event)
Beispiel #22
0
def _extract_parts(text):
    '''
        Extract Parts

        Extract and parse the message, returning a dictionary
        describing the actions that should be taken

        --
        @param  text:string    The message sent by the user

        @return dict
    '''

    # Examples:
    # remind me once monday at 4pm, Help!
    # remind me once two weeks from now, Help!
    #
    # remind me every 5 minutes, Help!
    # remind me every 1 day, Help!
    #
    # remind show
    # remind stop #1

    # With the above examples, we can say that the
    # format should follow the following:
    #
    # [script init] [set / show /stop / help] [once/every] [time]: [message]

    parts = {
        'recipient': None,
        'action': 'set',
        'recurrence': 'once',
        'time': None,
        'parsed_time': None,
        'message': None,
        'error': False,
        'error_message': None
    }

    # Check the action_recipient
    action_recipient = text.split(' ')[0].strip()

    # Ensure that the action is something we understand
    if action_recipient not in ['set', 'show', 'stop', 'help']:
        parts['error'] = True
        parts['error_message'] = 'Unknown command: {c}'.format(
            c=action_recipient)

        return parts

    # We are happy with the action. show and stop
    # actions dont care about the rest
    if action_recipient in ['show', 'stop', 'help']:
        parts['action'] = action_recipient
        return parts

    # Set the recipient and remove it from the text
    text = text.replace(action_recipient, '', 1).strip()
    parts['recipient'] = action_recipient

    # Next part is to check the recurrence.
    recurrence = text.split(' ')[0].strip()

    # Check that the recurrence is valid
    if recurrence not in ['once', 'every']:
        parts['error'] = True
        parts['error_message'] = 'Unknown recurrence: {r}'.format(r=recurrence)

        return parts

    # Set the recurrence and remove it from the text
    # only of it is set to 'once'
    text = text.replace('once', '', 1).strip()
    parts['recurrence'] = recurrence

    # Next, we parse the time. For this we should be
    # able to split by ,
    if len(text.split(',', 1)) != 2:
        parts['error'] = True
        parts[
            'error_message'] = 'Time and message should be seperated by a comma ( , ) character'

        return parts

    # Set the time and the message
    time = text.split(',', 1)[0].strip()
    message = text.split(',', 1)[1].strip()

    # Resolve the human time to something we can work
    # with
    r = RecurringEvent()
    parsed_time = r.parse(time)

    # If the time parsing failed, oh well.
    if parsed_time is None:
        parts['error'] = True
        parts['error_message'] = 'Unable to parse time: {t}'.format(t=time)

        return parts

    # Set the time and parsed time, as well as the message
    # that should be used
    parts['time'] = time
    parts['parsed_time'] = parsed_time
    parts['message'] = message

    return parts
Beispiel #23
0
def get_rrule(human_string):
    r = RecurringEvent(now_date=datetime.datetime.now())
    return r.parse(human_string)
Beispiel #24
0
def test_convert_recurring_event_to_trigger_format(frequency, expected):
    event = RecurringEvent()
    event.parse(frequency)
    assert parser.convert_recurring_event_to_trigger_format(event) == expected
    # validate with ApsSchedule cron trigger
    CronTrigger(**expected)
Beispiel #25
0
def is_day_in_recurrence(recurrence_string, day):
    recurrence = rrule.rrulestr(RecurringEvent().parse(recurrence_string))
    return (recurrence[0].date() - day.date()).days == 0
Beispiel #26
0
meeting_subject = "Hackathon Demo Meeting"
meeting_body = "Let\'s sync up for the Schedder hackathon demo."

message = sys.argv[1]
# First email in list is the login credentials to Microsoft API, and therefore also the sender of the invite
email = sys.argv[2]
users = sys.argv[2:]

# Can add additional rooms
rooms = ['*****@*****.**', '*****@*****.**']
room_map = {
    '*****@*****.**': 'SJC09-1-FURMAN',
    '*****@*****.**': 'SJC09-1-CHIMNEY ROCK'
}

r = RecurringEvent()
date = r.parse(message)
now = datetime.datetime.now()
if date is None:
    start = now
    end = start + datetime.timedelta(days=30)
else:
    if 'week' in message or 'month' in message or 'year' in message:
        # Get all meetings within business week
        weekday = date.weekday()
        if weekday == 5 or weekday == 6:
            # Saturday or Sunday consider next Monday
            start = date + datetime.timedelta(days=7 - weekday)
        else:
            # That week's Monday
            start = date - datetime.timedelta(days=weekday)
Beispiel #27
0
def slack_events(request):
    bod = request.json_body
    bot_token = os.environ.get('SLACK_BOT_TOKEN')
    if bod['token'] != bot_token:
        return Response(status=304)

    evt = bod['event']
    msg = evt['text']
    channel = evt['channel']
    user = evt['user']
    edited = evt.get('edited')
    if edited:
        user_ts = edited['ts']
    else:
        user_ts = evt['ts']
    print(user_ts)
    retry_count = request.headers.get('X-Slack-Retry-Num')
    if retry_count is not None and int(retry_count) > 0:
        thread = evt['ts']
    else:
        thread = None

    slack_api_key = os.environ.get('SLACK_API_KEY')
    slack_client = slack.WebClient(token=slack_api_key)
    user_ts = float(user_ts)
    # Parsing natural language with regex...we can add a context free grammar later...
    md = MSG_RGX.search(msg)
    if md:
        tgts = re.split(AND_OR_COMMA_RGX_STR, md.group('targets'))
        found_tgts = []
        query_str = md.group('query')
        # A list of available targets for this requester, a subset of all
        # possible targets (those in the message regex)
        potential_targets = get_potential_targets(request)
        for t in tgts:
            for s in potential_targets:
                if s.lower() == t.lower():
                    found_tgts.append(s)

        queries = []
        for t in found_tgts:
            queries.append(SEARCH_TARGETS[t]['query_type'](query_str))

        user_now = datetime.utcfromtimestamp(user_ts)
        sched = RecurringEvent(now_date=user_now)
        sched_str = md.group('schedule')
        if not sched_str:
            sched_str = 'daily'
        rrule_str = sched.parse(sched_str)
        if rrule_str:
            schedule = rrulestr(rrule_str)
            schedule.dtstart = user_now
            reply = (
                'OK, <@{}>, I will search for "{}" on {} with a schedule of "{}". '
                'The next query will be at {}')
            reply = reply.format(user, query_str, ", ".join(found_tgts),
                                 str(rrule_str), schedule.after(user_now))

            # TODO: Make this logic also account for per-user schedule requests,
            # org-level event handlers and storage
            key = ('slack_channel', channel)
            if SCHEDULER_KEY not in request.context:
                # TODO: Put this in a different place and use a remote search scheduler
                request.context[SCHEDULER_KEY] = PersistentDict()

            if key not in request.context[SCHEDULER_KEY]:
                request.context[SCHEDULER_KEY][key] = ListSearchScheduler()

            if HANDLER_KEY not in request.context:
                # TODO: Put this in a different place and use a remote event handler
                request.context[HANDLER_KEY] = PersistentDict()

            if key not in request.context[HANDLER_KEY]:
                request.context[HANDLER_KEY][key] = SlackMessageEventHandler(
                    channel, user)

            scheduler = request.context[SCHEDULER_KEY][key]
            event_handler = request.context[HANDLER_KEY][key]

            for q in queries:
                scheduler.add_schedule(q, schedule, event_handler)
        else:
            reply = f'Sorry, <@{user}>, but I don\'t understand this search schedule: {sched_str}'
    else:
        reply = f'Sorry, <@{user}>, I don\'t know about that'

    send_message(slack_client, evt['channel'], reply, thread)
    return Response('')
Beispiel #28
0
    def parse(self, goal_text):
        goal_text = goal_text.rstrip(string.punctuation)

        self.creation_text = goal_text

        index = goal_text.lower().find(self.EVERY)

        if index == -1:
            raise InvalidInput("Could not find the word '%s' in input" % self.EVERY)

        self.description = goal_text[:index].strip()

        try:
            goal_amount = self.incremental_parse(self.description)

            if goal_amount:
                self.incremental = True
                self.goal_amount = goal_amount
        except InvalidInput as i:
            raise i

        recurring_text = goal_text[index:].strip()

        recurring_event = RecurringEvent()

        result = None

        try:
            result = recurring_event.parse(recurring_text)
        except ValueError:
            raise InvalidInput("Not a recurring rule or not valid input")

        if type(result) != type('str'):
            raise InvalidInput("Not a recurring rule or not valid input")

        params = recurring_event.get_params()

        if params['freq'] in ['hourly', 'minutely', 'secondly']:
            raise InvalidInput("Not a recurring rule or not valid input")

        
        if params.has_key('dtstart'):
            naive = datetime.datetime.strptime(params['dtstart'], "%Y%m%d") 

            user_tz = pytz.timezone(self.user.userprofile.timezone)

            local_dt = user_tz.localize(naive, is_dst=None)
            utc_dt = local_dt.astimezone (pytz.utc)
            
            self.dtstart = utc_dt
        else:
            self.dtstart = Goal.beginning_today(self.user)

        self.rrule = recurring_event.get_RFC_rrule()

        if not self.rrule.startswith("DTSTART:"):
            self.rrule = "DTSTART:" + self.dtstart.strftime("%Y%m%d") + "\n" + self.rrule

        if params.get('freq', None):
            self.freq = params['freq']

        if params.get('byday', None):
            self.byday = params['byday']
Beispiel #29
0
    mqttc.username_pw_set(cf.get('mqtt_username'), cf.get('mqtt_password'))

    mqtt_port = int(cf.get('mqtt_port', '1883'))
    ssl = (mqtt_port == 8883)
    if ssl:
        mqttc.tls_set(ca_certs=None, certfile=None, keyfile=None, cert_reqs=paho.ssl.CERT_REQUIRED, tls_version=paho.ssl.PROTOCOL_TLS, ciphers=None)
    
    mqttc.connect(cf.get('mqtt_broker', 'localhost'), mqtt_port, 60)

    # parse schedule
    schedule = cf.get('schedule', {})
    s = sched.scheduler(time.time, time.sleep)
    now = datetime.now()
    for t in schedule:
        r = RecurringEvent()
        dt = r.parse(t)
        if not r.is_recurring:
            logging.error(t + " is not recurring time. Skipping")
            continue
        delay = (rrulestr(dt).after(now) - now).total_seconds()
        s.enter(delay, 1, on_timer, [s, dt, schedule[t]])

    tt = TimerThread(s)
    tt.daemon = True
    tt.start()

    while True:
        try:
            mqttc.loop_forever()
        except socket.error:
Beispiel #30
0
def parse_time(event):
    event = event.replace('AM', 'am').replace('PM', 'pm')
    dt = datetime.datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0)
    r = RecurringEvent(now_date=dt)
    start_date, success = r.parse_time(event, dt)
    return start_date.time(), success
Beispiel #31
0
    mqttc.will_set('clients/psmqtt', payload="Adios!", qos=0, retain=False)

    # Delays will be: 3, 6, 12, 24, 30, 30, ...
    # mqttc.reconnect_delay_set(delay=3, delay_max=30, exponential_backoff=True)

    mqttc.username_pw_set(cf.get('mqtt_username'), cf.get('mqtt_password'))

    mqttc.connect(cf.get('mqtt_broker', 'localhost'), int(cf.get('mqtt_port', '1883')), 60)

    # parse schedule
    schedule = cf.get('schedule', {})
    s = sched.scheduler(time.time, time.sleep)
    now = datetime.now()
    for t in schedule:
        r = RecurringEvent()
        dt = r.parse(t)
        if not r.is_recurring:
            logging.error(t + " is not recurring time. Skipping")
            continue
        delay = (rrulestr(dt).after(now) - now).total_seconds()
        s.enter(delay, 1, on_timer, [s, dt, schedule[t]])

    tt = TimerThread(s)
    tt.daemon = True
    tt.start()

    while True:
        try:
            mqttc.loop_forever()
        except socket.error:
Beispiel #32
0
def _extract_parts (text):
    '''
        Extract Parts

        Extract and parse the message, returning a dictionary
        describing the actions that should be taken

        --
        @param  text:string    The message sent by the user

        @return dict
    '''

    # Examples:
    # remind me once monday at 4pm, Help!
    # remind me once two weeks from now, Help!
    #
    # remind me every 5 minutes, Help!
    # remind me every 1 day, Help!
    #
    # remind show
    # remind stop #1

    # With the above examples, we can say that the
    # format should follow the following:
    #
    # [script init] [set / show /stop / help] [once/every] [time]: [message]

    parts = {

        'recipient': None,
        'action': 'set',
        'recurrence': 'once',
        'time': None,
        'parsed_time': None,
        'message': None,
        'error': False,
        'error_message': None
    }

    # Check the action_recipient
    action_recipient = text.split(' ')[0].strip()

    # Ensure that the action is something we understand
    if action_recipient not in ['set', 'show', 'stop', 'help']:
        parts['error'] = True
        parts['error_message'] = 'Unknown command: {c}'.format(
            c = action_recipient
        )

        return parts

    # We are happy with the action. show and stop
    # actions dont care about the rest
    if action_recipient in ['show', 'stop', 'help']:
        parts['action'] = action_recipient
        return parts

    # Set the recipient and remove it from the text
    text = text.replace(action_recipient, '', 1).strip()
    parts['recipient'] = action_recipient

    # Next part is to check the recurrence.
    recurrence = text.split(' ')[0].strip()

    # Check that the recurrence is valid
    if recurrence not in ['once', 'every']:
        parts['error'] = True
        parts['error_message'] = 'Unknown recurrence: {r}'.format(
            r = recurrence
        )

        return parts

    # Set the recurrence and remove it from the text
    # only of it is set to 'once'
    text = text.replace('once', '', 1).strip()
    parts['recurrence'] = recurrence

    # Next, we parse the time. For this we should be
    # able to split by ,
    if len(text.split(',', 1)) != 2:
        parts['error'] = True
        parts['error_message'] = 'Time and message should be seperated by a comma ( , ) character'

        return parts

    # Set the time and the message
    time = text.split(',', 1)[0].strip()
    message = text.split(',', 1)[1].strip()

    # Resolve the human time to something we can work
    # with
    r = RecurringEvent()
    parsed_time = r.parse(time)

    # If the time parsing failed, oh well.
    if parsed_time is None:
        parts['error'] = True
        parts['error_message'] = 'Unable to parse time: {t}'.format(
            t = time
        )

        return parts

    # Set the time and parsed time, as well as the message
    # that should be used
    parts['time'] = time
    parts['parsed_time'] = parsed_time
    parts['message'] = message

    return parts