Text Me Maybe: Smarter Real-World Integrations with Python
Slides from my PyOhio 2016 talk about combining IFTTT (If This Then That), AWS Lambda and API Gateway, Twilio, and Python to make a location-triggered SMS notifier that's also sensitive to days and times.
a server • Build a TCPA-compliant SMS integration • Write and deploy a REST API • Write a geofenced mobile app and get it deployed to your device • Write the code you actually care about • Probably more things you don’t care about
a server • Build a TCPA-compliant SMS integration • Write and deploy a REST API • Write a geofenced mobile app and get it deployed to your device • Write the code you actually care about • Probably more things you don’t care about X
client = TwilioRestClient(account_sid, auth_token) def send_sms(to_phone, from_phone, body): """ Send an SMS message containing a particular body to a phone number from a phone number. """ return client.messages.create(to=to_phone, from_=from_phone, body=body) message = send_sms(to_phone, from_phone, message_body)
client = TwilioRestClient(account_sid, auth_token) def send_sms(to_phone, from_phone, body): """ Send an SMS message containing a particular body to a phone number from a phone number. """ return client.messages.create(to=to_phone, from_=from_phone, body=body) message = send_sms(to_phone, from_phone, message_body)
client = TwilioRestClient(account_sid, auth_token) def send_sms(to_phone, from_phone, body): """ Send an SMS message containing a particular body to a phone number from a phone number. """ return client.messages.create(to=to_phone, from_=from_phone, body=body) message = send_sms(to_phone, from_phone, message_body)
client = TwilioRestClient(account_sid, auth_token) def send_sms(to_phone, from_phone, body): """ Send an SMS message containing a particular body to a phone number from a phone number. """ return client.messages.create(to=to_phone, from_=from_phone, body=body) message = send_sms(to_phone, from_phone, message_body)
datetime) between two other times (as 24-hour 'HHMM' strings)? """ # Convert HHMM strings into tuples hhmm1 = tuple([int(x) for x in [t1[:2], t1[2:]]]) hhmm2 = tuple([int(x) for x in [t2[:2], t2[2:]]]) hhmm = now.hour, now.minute # Start time before end time; span stays within day if hhmm1 <= hhmm2: return hhmm1 <= hhmm <= hhmm2 # End time before start time; span crosses midnight else: return (hhmm1 <= hhmm <= (23, 59)) or \ ((0, 0) <= hhmm <= hhmm2) import datetime now = datetime.datetime.utcnow() if is_time_between(now, t1, t2): message = send_sms(to_phone, from_phone, message_body)
datetime) between two other times (as 24-hour 'HHMM' strings)? """ # Convert HHMM strings into tuples hhmm1 = tuple([int(x) for x in [t1[:2], t1[2:]]]) hhmm2 = tuple([int(x) for x in [t2[:2], t2[2:]]]) hhmm = now.hour, now.minute # Start time before end time; span stays within day if hhmm1 <= hhmm2: return hhmm1 <= hhmm <= hhmm2 # End time before start time; span crosses midnight else: return (hhmm1 <= hhmm <= (23, 59)) or \ ((0, 0) <= hhmm <= hhmm2) import datetime now = datetime.datetime.utcnow() if is_time_between(now, t1, t2): message = send_sms(to_phone, from_phone, message_body)
datetime) between two other times (as 24-hour 'HHMM' strings)? """ # Convert HHMM strings into tuples hhmm1 = tuple([int(x) for x in [t1[:2], t1[2:]]]) hhmm2 = tuple([int(x) for x in [t2[:2], t2[2:]]]) hhmm = now.hour, now.minute # Start time before end time; span stays within day if hhmm1 <= hhmm2: return hhmm1 <= hhmm <= hhmm2 # End time before start time; span crosses midnight else: return (hhmm1 <= hhmm <= (23, 59)) or \ ((0, 0) <= hhmm <= hhmm2) import datetime now = datetime.datetime.utcnow() if is_time_between(now, t1, t2): message = send_sms(to_phone, from_phone, message_body)
datetime) between two other times (as 24-hour 'HHMM' strings)? """ # Convert HHMM strings into tuples hhmm1 = tuple([int(x) for x in [t1[:2], t1[2:]]]) hhmm2 = tuple([int(x) for x in [t2[:2], t2[2:]]]) hhmm = now.hour, now.minute # Start time before end time; span stays within day if hhmm1 <= hhmm2: return hhmm1 <= hhmm <= hhmm2 # End time before start time; span crosses midnight else: return (hhmm1 <= hhmm <= (23, 59)) or \ ((0, 0) <= hhmm <= hhmm2) import datetime now = datetime.datetime.utcnow() if is_time_between(now, t1, t2): message = send_sms(to_phone, from_phone, message_body)
datetime) between two other times (as 24-hour 'HHMM' strings)? """ # Convert HHMM strings into tuples hhmm1 = tuple([int(x) for x in [t1[:2], t1[2:]]]) hhmm2 = tuple([int(x) for x in [t2[:2], t2[2:]]]) hhmm = now.hour, now.minute # Start time before end time; span stays within day if hhmm1 <= hhmm2: return hhmm1 <= hhmm <= hhmm2 # End time before start time; span crosses midnight else: return (hhmm1 <= hhmm <= (23, 59)) or \ ((0, 0) <= hhmm <= hhmm2) import datetime now = datetime.datetime.utcnow() if is_time_between(now, t1, t2): message = send_sms(to_phone, from_phone, message_body)
[t1[:2], t1[2:]]]) get the first 2 characters get the last 2 characters list comprehension: turn everything into a list of integers turn the list into a tuple put them in a list
among particular ISO 8601 (Monday = 1) days? """ return not days or now.isoweekday() in days now = datetime.datetime.utcnow() days = [1, 2, 3, 4, 5] if (is_time_between(now, t1, t2) and is_day_allowed(now, days)): message = send_sms(to_phone, from_phone, message_body)
among particular ISO 8601 (Monday = 1) days? """ return not days or now.isoweekday() in days now = datetime.datetime.utcnow() days = [1, 2, 3, 4, 5] if (is_time_between(now, t1, t2) and is_day_allowed(now, days)): message = send_sms(to_phone, from_phone, message_body)
among particular ISO 8601 (Monday = 1) days? """ return not days or now.isoweekday() in days now = datetime.datetime.utcnow() days = [1, 2, 3, 4, 5] if (is_time_between(now, t1, t2) and is_day_allowed(now, days)): message = send_sms(to_phone, from_phone, message_body)
event (dict) and context (LambdaContext) and sends an SMS message to the specified phone number(s) if the time is within the specified window. """ now = datetime.datetime.utcnow() t1, t2 = event.get('t1', '0000'), event.get('t2', '0000') days = [int(x) for x in event.get('days', '')] if (is_time_between(now, t1, t2) and is_day_allowed(now, days)): to_phone = event['to_phone'] message = send_sms(to_phone, from_phone, event['message']) return {'result': messages.SENT} else: return {'result': messages.NOT_SENT}
event (dict) and context (LambdaContext) and sends an SMS message to the specified phone number(s) if the time is within the specified window. """ now = datetime.datetime.utcnow() t1, t2 = event.get('t1', '0000'), event.get('t2', '0000') days = [int(x) for x in event.get('days', '')] if (is_time_between(now, t1, t2) and is_day_allowed(now, days)): to_phone = event['to_phone'] message = send_sms(to_phone, from_phone, event['message']) return {'result': messages.SENT} else: return {'result': messages.NOT_SENT}
event (dict) and context (LambdaContext) and sends an SMS message to the specified phone number(s) if the time is within the specified window. """ now = datetime.datetime.utcnow() t1, t2 = event.get('t1', '0000'), event.get('t2', '0000') days = [int(x) for x in event.get('days', '')] if (is_time_between(now, t1, t2) and is_day_allowed(now, days)): to_phone = event['to_phone'] message = send_sms(to_phone, from_phone, event['message']) return {'result': messages.SENT} else: return {'result': messages.NOT_SENT}
event (dict) and context (LambdaContext) and sends an SMS message to the specified phone number(s) if the time is within the specified window. """ now = datetime.datetime.utcnow() t1, t2 = event.get('t1', '0000'), event.get('t2', '0000') days = [int(x) for x in event.get('days', '')] if (is_time_between(now, t1, t2) and is_day_allowed(now, days)): to_phone = event['to_phone'] message = send_sms(to_phone, from_phone, event['message']) return {'result': messages.SENT} else: return {'result': messages.NOT_SENT}
= [int(x) for x in event.get('days', '')] try to get t1 from the event dictionary, fall back to '0000' try to get t2 from the event dictionary, fall back to '0000'
= [int(x) for x in event.get('days', '')] try to get t1 from the event dictionary, fall back to '0000' try to get t2 from the event dictionary, fall back to '0000' assign the values into t1 and t2 in a single step
= [int(x) for x in event.get('days', '')] try to get t1 from the event dictionary, fall back to '0000' try to get t2 from the event dictionary, fall back to '0000' try to get days from the event dictionary, fall back to '' assign the values into t1 and t2 in a single step
= [int(x) for x in event.get('days', '')] try to get t1 from the event dictionary, fall back to '0000' try to get t2 from the event dictionary, fall back to '0000' try to get days from the event dictionary, fall back to '' list comprehension: turn everything into a list of integers assign the values into t1 and t2 in a single step