def is_recurring(event): r = RecurringEvent(now_date=datetime.datetime.utcnow()) try: r.parse(event) return r.is_recurring except ValueError: return False
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, {}
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])
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 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
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 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)
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"]
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')
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 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'})
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])
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
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: time.sleep(5)
def get_rrule(human_string): r = RecurringEvent(now_date=datetime.datetime.now()) return r.parse(human_string)
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)
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})
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']
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
def is_event_recurring(s): r = RecurringEvent(now_date=datetime.datetime.now()) r.parse(s) return r.is_recurring
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)
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('')
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: time.sleep(5)
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) end = start + datetime.timedelta(days=4)
def non_recurrent_parse(event): r = RecurringEvent(now_date=datetime.datetime.utcnow()) return r.parse(event)
def contains_date(event): r = RecurringEvent(now_date=datetime.datetime.utcnow()) try: return r.parse(event) is not None except ValueError: return False