some linting, a little var renaming

This commit is contained in:
2019-08-20 15:13:22 +02:00
parent 0908ce057f
commit 548a74cd0d
7 changed files with 700 additions and 28 deletions

53
Pipfile Normal file
View File

@@ -0,0 +1,53 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
appnope = "==0.1.0"
certifi = "==2017.4.17"
chardet = "==3.0.4"
click = "==6.7"
decorator = "==4.0.11"
falcon = "==1.2.0"
future = "==0.16.0"
google-api-python-client = "==1.6.2"
httplib2 = "==0.10.3"
hug = "==2.3.0"
idna = "==2.6"
ipython = "==6.1.0"
itsdangerous = "==0.24"
jedi = "==0.10.2"
oauth2client = "==4.1.1"
parsedatetime = "==2.4"
parso = "==0.1.0"
pexpect = "==4.2.1"
pickleshare = "==0.7.4"
ptyprocess = "==0.5.1"
pyasn1 = "==0.2.3"
pyasn1-modules = "==0.0.9"
python-mimeparse = "==1.6.0"
pytz = "==2017.2"
requests = "==2.18.4"
rsa = "==3.4.2"
simplegeneric = "==0.8.1"
six = "==1.10.0"
traitlets = "==4.3.2"
twilio = "==6.8.1"
uritemplate = "==3.0.0"
urllib3 = "==1.21.1"
wcwidth = "==0.1.7"
Flask = "==0.12.2"
ipython_genutils = "==0.2.0"
Jinja2 = "==2.9.6"
MarkupSafe = "==1.0"
prompt_toolkit = "==1.0.14"
Pygments = "==2.2.0"
PyJWT = "==1.5.0"
PySocks = "==1.6.7"
Werkzeug = "==0.12.2"
[requires]
python_version = "3.7"

354
Pipfile.lock generated Normal file
View File

@@ -0,0 +1,354 @@
{
"_meta": {
"hash": {
"sha256": "3ebef50f16c7bb5fb3eca23f8217d8d093c03d7392e668b62489bd280d9977fb"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.7"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"appnope": {
"hashes": [
"sha256:5b26757dc6f79a3b7dc9fab95359328d5747fcb2409d331ea66d0272b90ab2a0",
"sha256:8b995ffe925347a2138d7ac0fe77155e4311a0ea6d6da4f5128fe4b3cbe5ed71"
],
"index": "pypi",
"version": "==0.1.0"
},
"certifi": {
"hashes": [
"sha256:f4318671072f030a33c7ca6acaef720ddd50ff124d1388e50c1bda4cbd6d7010",
"sha256:f7527ebf7461582ce95f7a9e03dd141ce810d40590834f4ec20cddd54234c10a"
],
"index": "pypi",
"version": "==2017.4.17"
},
"chardet": {
"hashes": [
"sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
"sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
],
"index": "pypi",
"version": "==3.0.4"
},
"click": {
"hashes": [
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
],
"index": "pypi",
"version": "==6.7"
},
"decorator": {
"hashes": [
"sha256:73cbaadb8bc4e3c65fe1100773d56331a2d756cc0f5c7b9d8d5d5223fe04f600",
"sha256:953d6bf082b100f43229cf547f4f97f97e970f5ad645ee7601d55ff87afdfe76"
],
"index": "pypi",
"version": "==4.0.11"
},
"falcon": {
"hashes": [
"sha256:53bb5119d2513613eef6868c829ad47606615ff619590e05f7068a955867173d",
"sha256:6f125ce285a8e9124147497a8d4c202a7316ee550d3ceb003f64d2c5740a9805"
],
"index": "pypi",
"version": "==1.2.0"
},
"flask": {
"hashes": [
"sha256:0749df235e3ff61ac108f69ac178c9770caeaccad2509cb762ce1f65570a8856",
"sha256:49f44461237b69ecd901cc7ce66feea0319b9158743dd27a2899962ab214dac1"
],
"index": "pypi",
"version": "==0.12.2"
},
"future": {
"hashes": [
"sha256:e39ced1ab767b5936646cedba8bcce582398233d6a627067d4c6a454c90cfedb"
],
"index": "pypi",
"version": "==0.16.0"
},
"google-api-python-client": {
"hashes": [
"sha256:8c2f50f8057571a5f817c74820cadb754d47799c5a4ea463c1500fe8e092c1ae",
"sha256:c0f4bcf398c937a43f382eecb384ba9b3a97ef9c24b156420b1b396fcaadd0af"
],
"index": "pypi",
"version": "==1.6.2"
},
"httplib2": {
"hashes": [
"sha256:e404d3b7bd86c1bc931906098e7c1305d6a3a6dcef141b8bb1059903abb3ceeb"
],
"index": "pypi",
"version": "==0.10.3"
},
"hug": {
"hashes": [
"sha256:2d3b56368a9c07804a244067f08f5c194d555ca05c90ad48445c72d38fb6b7a1"
],
"index": "pypi",
"version": "==2.3.0"
},
"idna": {
"hashes": [
"sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f",
"sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4"
],
"index": "pypi",
"version": "==2.6"
},
"ipython": {
"hashes": [
"sha256:5c53e8ee4d4bec27879982b9f3b4aa2d6e3cfd7b26782d250fa117f85bb29814",
"sha256:cd44c7f5ccb2b349ffd6ede10d8e4204c9ab1ede4a8a6c40220cfeb07069171a"
],
"index": "pypi",
"version": "==6.1.0"
},
"ipython-genutils": {
"hashes": [
"sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8",
"sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"
],
"index": "pypi",
"version": "==0.2.0"
},
"itsdangerous": {
"hashes": [
"sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
],
"index": "pypi",
"version": "==0.24"
},
"jedi": {
"hashes": [
"sha256:7abb618cac6470ebbd142e59c23daec5e6e063bfcecc8a43a037d2ab57276f4e",
"sha256:96678411f2ffa444da3a5e7fdd4adc513b728a4a4617b30308be5c950722424b"
],
"index": "pypi",
"version": "==0.10.2"
},
"jinja2": {
"hashes": [
"sha256:2231bace0dfd8d2bf1e5d7e41239c06c9e0ded46e70cc1094a0aa64b0afeb054",
"sha256:ddaa01a212cd6d641401cb01b605f4a4d9f37bfc93043d7f760ec70fb99ff9ff"
],
"index": "pypi",
"version": "==2.9.6"
},
"markupsafe": {
"hashes": [
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
],
"index": "pypi",
"version": "==1.0"
},
"oauth2client": {
"hashes": [
"sha256:ed0c670f09db32444f843d5d2f92df00733751dfec9a28b0fd3f00693ff36a04",
"sha256:fd02b705092b76f443028328eaed366135f26c0d3e52bdbf66e649a944938ca1"
],
"index": "pypi",
"version": "==4.1.1"
},
"parsedatetime": {
"hashes": [
"sha256:3d817c58fb9570d1eec1dd46fa9448cd644eeed4fb612684b02dfda3a79cb84b",
"sha256:9ee3529454bf35c40a77115f5a596771e59e1aee8c53306f346c461b8e913094"
],
"index": "pypi",
"version": "==2.4"
},
"parso": {
"hashes": [
"sha256:b573acb69f66a970197b5fdbbdfad3b8a417a520e383133b2b4e708f104bfc9a",
"sha256:c5279916bb417aa2bf634648ff895cf35dce371d7319744884827bfad06f8d7b"
],
"index": "pypi",
"version": "==0.1.0"
},
"pexpect": {
"hashes": [
"sha256:3d132465a75b57aa818341c6521392a06cc660feb3988d7f1074f39bd23c9a92",
"sha256:f853b52afaf3b064d29854771e2db509ef80392509bde2dd7a6ecf2dfc3f0018"
],
"index": "pypi",
"version": "==4.2.1"
},
"pickleshare": {
"hashes": [
"sha256:84a9257227dfdd6fe1b4be1319096c20eb85ff1e82c7932f36efccfe1b09737b",
"sha256:c9a2541f25aeabc070f12f452e1f2a8eae2abd51e1cd19e8430402bdf4c1d8b5"
],
"index": "pypi",
"version": "==0.7.4"
},
"prompt-toolkit": {
"hashes": [
"sha256:7281b5199235adaef6980942840c43753e4ab20dfe41338da634fb41c194f9d8",
"sha256:82c7f8e07d7a0411ff5367a5a8ff520f0112b9179f3e599ee8ad2ad9b943d911",
"sha256:cc66413b1b4b17021675d9f2d15d57e640b06ddfd99bb724c73484126d22622f"
],
"index": "pypi",
"version": "==1.0.14"
},
"ptyprocess": {
"hashes": [
"sha256:0530ce63a9295bfae7bd06edc02b6aa935619f486f0f1dc0972f516265ee81a6",
"sha256:464cb76f7a7122743dd25507650db89cd447c51f38e4671602b3eaa2e38e05ae"
],
"index": "pypi",
"version": "==0.5.1"
},
"pyasn1": {
"hashes": [
"sha256:0439b9bd518418260c2641a571f0e07fce4370cab13b68f19b5e023306c03cad",
"sha256:738c4ebd88a718e700ee35c8d129acce2286542daa80a82823a7073644f706ad"
],
"index": "pypi",
"version": "==0.2.3"
},
"pyasn1-modules": {
"hashes": [
"sha256:9d5008b0c3dc5685aac7977951e7fb222736d5fd817c810fa0cfb08c5fd71630",
"sha256:be0e4157e4a53551279d6c6e366b080527f5fd068616835b4abf32c14f657f5f"
],
"index": "pypi",
"version": "==0.0.9"
},
"pygments": {
"hashes": [
"sha256:78f3f434bcc5d6ee09020f92ba487f95ba50f1e3ef83ae96b9d5ffa1bab25c5d",
"sha256:dbae1046def0efb574852fab9e90209b23f556367b5a320c0bcb871c77c3e8cc"
],
"index": "pypi",
"version": "==2.2.0"
},
"pyjwt": {
"hashes": [
"sha256:ad60a3fb9b393667864ed4b8abc9c3b570747f80bf77a113ead2fbaf0f0cedf3",
"sha256:fd182b728d13f04c289d9b2623d09256d356c9b4a6778018001454a954d7c54b"
],
"index": "pypi",
"version": "==1.5.0"
},
"pysocks": {
"hashes": [
"sha256:18842328a4e6061f084cfba70f6950d9140ecf7418b3df7cef558ebb217bac8d",
"sha256:d00329f27efa157db7efe3ca26fcd69033cd61f83822461ee3f8a353b48e33cf"
],
"index": "pypi",
"markers": "python_version >= '3.0'",
"version": "==1.6.7"
},
"python-mimeparse": {
"hashes": [
"sha256:76e4b03d700a641fd7761d3cd4fdbbdcd787eade1ebfac43f877016328334f78",
"sha256:a295f03ff20341491bfe4717a39cd0a8cc9afad619ba44b77e86b0ab8a2b8282"
],
"index": "pypi",
"version": "==1.6.0"
},
"pytz": {
"hashes": [
"sha256:d1d6729c85acea5423671382868627129432fba9a89ecbb248d8d1c7a9f01c67",
"sha256:f5c056e8f62d45ba8215e5cb8f50dfccb198b4b9fbea8500674f3443e4689589"
],
"index": "pypi",
"version": "==2017.2"
},
"requests": {
"hashes": [
"sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b",
"sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e"
],
"index": "pypi",
"version": "==2.18.4"
},
"rsa": {
"hashes": [
"sha256:25df4e10c263fb88b5ace923dd84bf9aa7f5019687b5e55382ffcdb8bede9db5",
"sha256:43f682fea81c452c98d09fc316aae12de6d30c4b5c84226642cf8f8fd1c93abd"
],
"index": "pypi",
"version": "==3.4.2"
},
"simplegeneric": {
"hashes": [
"sha256:dc972e06094b9af5b855b3df4a646395e43d1c9d0d39ed345b7393560d0b9173"
],
"index": "pypi",
"version": "==0.8.1"
},
"six": {
"hashes": [
"sha256:0ff78c403d9bccf5a425a6d31a12aa6b47f1c21ca4dc2573a7e2f32a97335eb1",
"sha256:105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a"
],
"index": "pypi",
"version": "==1.10.0"
},
"traitlets": {
"hashes": [
"sha256:9c4bd2d267b7153df9152698efb1050a5d84982d3384a37b2c1f7723ba3e7835",
"sha256:c6cb5e6f57c5a9bdaa40fa71ce7b4af30298fbab9ece9815b5d995ab6217c7d9"
],
"index": "pypi",
"version": "==4.3.2"
},
"twilio": {
"hashes": [
"sha256:919a603186afb69c25746a65e9b1956e02531d4a763b311d546c4857fdf16e67",
"sha256:f146ac865bfdca3a79deb07aa3176d0a66a110a2ad55201792938e1af452d9ac"
],
"index": "pypi",
"version": "==6.8.1"
},
"uritemplate": {
"hashes": [
"sha256:01c69f4fe8ed503b2951bef85d996a9d22434d2431584b5b107b2981ff416fbd",
"sha256:1b9c467a940ce9fb9f50df819e8ddd14696f89b9a8cc87ac77952ba416e0a8fd",
"sha256:c02643cebe23fc8adb5e6becffe201185bf06c40bda5c0b4028a93f1527d011d"
],
"index": "pypi",
"version": "==3.0.0"
},
"urllib3": {
"hashes": [
"sha256:8ed6d5c1ff9d6ba84677310060d6a3a78ca3072ce0684cb3c645023009c114b1",
"sha256:b14486978518ca0901a76ba973d7821047409d7f726f22156b24e83fd71382a5"
],
"index": "pypi",
"version": "==1.21.1"
},
"wcwidth": {
"hashes": [
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
"index": "pypi",
"version": "==0.1.7"
},
"werkzeug": {
"hashes": [
"sha256:903a7b87b74635244548b30d30db4c8947fe64c5198f58899ddcd3a13c23bb26",
"sha256:e8549c143af3ce6559699a01e26fa4174f4c591dbee0a499f3cd4c3781cdec3d"
],
"index": "pypi",
"version": "==0.12.2"
}
},
"develop": {}
}

View File

@@ -49,11 +49,13 @@ def add_sitter(body: str) -> Tuple[str, str]:
assert len(num_only) == 10
sitters[lowercase_name] = f'+1{num_only}'
phone_number = f'+1{num_only}'
sitters[lowercase_name] = {'num': phone_number,
'name': lowercase_name}
return name, sitters[lowercase_name]
return name, phone_number
if __name__ == '__main__':
app.run(debug=True, port=8000)
app.run(debug=True, port=8000, use_reloader=False)

View File

@@ -11,13 +11,13 @@ BOOKER_NUM = os.getenv('MY_TWILIO_NUM')
twilio_client = TwilioClient(os.getenv('TWILIO_SID'), os.getenv('TWILIO_TOKEN'))
app = Flask(__name__)
app.config.from_object(__name__)
sitters = {}
if os.path.exists('sitters.p'):
sitters = pickle.load(open('sitters.p', 'rb'))
app = Flask(__name__)
app.config.from_object(__name__)
@app.route('/bot', methods=['POST'])
def bot():
from_ = request.values.get('From')
@@ -91,5 +91,5 @@ if __name__ == '__main__':
sitter_list = 'Your sitters are ' + ' and '.join(
f'{sitter_name.title()}' for sitter_name in sitters) + '.'
twilio_client.api.account.messages.create(to=MY_CELL, from_=BOOKER_NUM, body=sitter_list)
app.run(debug=True, port=8000)
print(sitter_list)
app.run(debug=True, port=8000, use_reloader=False)

View File

@@ -14,7 +14,7 @@ from twilio.twiml.messaging_response import MessagingResponse
twilio_client = TwilioClient(os.getenv('TWILIO_SID'), os.getenv('TWILIO_TOKEN'))
MY_CELL = os.getenv('MY_CELL')
BOOKER_NUM = os.getenv('MY_TWILIO_NUM')
BOT_NUM = os.getenv('MY_TWILIO_NUM')
COUNTRY_CODE = f'+{os.getenv("TWILIO_COUNTRY_CODE")}'
TIMEOUT_MINUTES = 120
@@ -70,11 +70,11 @@ def bot() -> str:
else:
try:
start_time, end_time = request_booking(body)
start_datetime, end_time = request_booking(body)
except ValueError:
response = 'Please specify an end time (e.g. "tomorrow 5pm to 10pm").'
else:
booking_string = make_booking_string(start_time, end_time)
booking_string = make_booking_string(start_datetime, end_time)
response = f'Okay, I will reach out to the sitters about sitting on {booking_string}.'
if response is None:
@@ -165,8 +165,8 @@ def accept_or_decline(sitter_name: str, body: str) -> str:
return f'Okay, no problem, {sitter_name.title()}! Next time.'
def make_booking_string(start_time: datetime.datetime, end_time: datetime.time) -> str:
start_time_and_date_string = start_time.strftime('%-m/%-d from %-I:%M%p')
def make_booking_string(start_datetime: datetime.datetime, end_time: datetime.time) -> str:
start_time_and_date_string = start_datetime.strftime('%-m/%-d from %-I:%M%p')
end_time_string = end_time.strftime('%-I:%M%p')
return f'{start_time_and_date_string} to {end_time_string}'
@@ -236,12 +236,12 @@ def book_forever():
def offer_booking(sitter_dict: dict, booking_string: str) -> None:
message = f'{sitter_dict["name"].title()}, are you available to babysit on {booking_string}?'
twilio_client.api.account.messages.create(to=sitter_dict['num'],
from_=BOOKER_NUM,
from_=BOT_NUM,
body=message)
def update_client(string: str) -> None:
twilio_client.api.account.messages.create(to=MY_CELL, from_=BOOKER_NUM, body=string)
twilio_client.api.account.messages.create(to=MY_CELL, from_=BOT_NUM, body=string)
def has_phone_num(string):
@@ -249,19 +249,19 @@ def has_phone_num(string):
def request_booking(body: str) -> Tuple[datetime.datetime, datetime.time]:
session_start, session_end = parse_booking_request(body)
session_start_datetime, session_end_time = parse_booking_request(body)
global bookings
bookings = load_from_pickle('bookings')
bookings[(session_start, session_end)] = {'offered': dict()}
bookings[(session_start_datetime, session_end_time)] = {'offered': dict()}
persist_bookings()
return session_start, session_end
return session_start_datetime, session_end_time
def parse_booking_request(body: str) -> Tuple[datetime.datetime, datetime.time]:
start_string, end_string = body.split(' to ')
session_start = cal.parseDT(start_string)[0]
session_start_datetime = cal.parseDT(start_string)[0]
session_end_time = datetime.time(cal.parse(end_string)[0].tm_hour)
return session_start, session_end_time
return session_start_datetime, session_end_time
def add_sitter(body: str) -> Tuple[str, str]:
@@ -306,5 +306,5 @@ if __name__ == '__main__':
'I\'ll try to book one of our sitters!')
p = Process(target=book_forever)
p.start()
app.run(debug=True, port=8000)
app.run(debug=True, port=8000, use_reloader=False)
p.join()

View File

@@ -0,0 +1,263 @@
import datetime
from multiprocessing import Process
import os
from pprint import pprint
import time
from typing import Tuple, Dict
import parsedatetime as pdt
import pickle
from flask import request, Flask
from twilio.rest import Client as TwilioClient
from twilio.twiml.messaging_response import MessagingResponse
twilio_client = TwilioClient(os.getenv('TWILIO_SID'), os.getenv('TWILIO_TOKEN'))
MY_CELL = os.getenv('MY_CELL')
BOT_NUM = os.getenv('MY_TWILIO_NUM')
COUNTRY_CODE = f'+{os.getenv("TWILIO_COUNTRY_CODE")}'
TIMEOUT_MINUTES = 120
help_add = 'You can add a sitter by giving me their first name and 10-digit phone number'
help_text = help_add + ', or book a sitter by ' \
'specifying a date and time. You can also remove a sitter from the list ' \
'with "delete" or "remove" and then their first name.'
app = Flask(__name__)
app.config.from_object(__name__)
cal = pdt.Calendar()
class TheresAlreadyAnActiveBooking(Exception):
pass
def load_from_pickle(var_name: str) -> dict:
payload = {}
if os.path.exists(f'{var_name}.p'):
payload = pickle.load(open(f'{var_name}.p', 'rb'))
return payload
sitters, bookings = load_from_pickle('sitters'), load_from_pickle('bookings')
sitters_num_name_lookup = {v['num']: k for k, v in sitters.items()}
@app.route('/bot', methods=['POST'])
def bot() -> str:
from_ = request.values.get('From')
body = request.values.get('Body').lower()
resp = MessagingResponse()
response = ''
if from_ == MY_CELL:
if has_phone_num(body):
try:
sitter_name, sitter_num = add_sitter(body)
except (AssertionError, ValueError):
response = 'Sorry, did you mean to add a sitter? Please try again.'
else:
response = f'Okay, I added {sitter_name.title()} to sitters, with phone # {sitter_num}. '
elif any(remove_word in body for remove_word in ['remove', 'delete']):
try:
sitter_name = remove_sitter(body)
except KeyError:
response = 'No such sitter. Please write "delete [sitter\'s first name]."'
else:
response = f'Okay, I removed {sitter_name.title()} from the sitters.'
else:
try:
start_datetime, end_time = request_booking(body)
except ValueError:
response = 'Please specify an end time (e.g. "tomorrow 5pm to 10pm").'
except TheresAlreadyAnActiveBooking:
response = 'Please wait until the current booking is either booked or expires.'
else:
booking_string = make_booking_string(start_datetime, end_time)
response = f'Okay, I will reach out to the sitters about sitting on {booking_string}.'
if response is None:
response = 'I wasn\'t sure what to do with your input. ' + help_text
else:
sitter_name = sitters_num_name_lookup.get(from_)
if sitter_name is not None:
response = accept_or_decline(sitter_name, body)
resp.message(response)
return str(resp)
def accept_or_decline(sitter_name: str, body: str) -> str:
body = body.strip()
global bookings
global sitters
bookings, sitters = load_from_pickle('bookings'), load_from_pickle('sitters')
sitter = sitters[sitter_name]
sitter_offers = [k for k, v in bookings.items()
if sitter_name in v['offered']
if v['offered'][sitter_name] not in ['yes', 'no']]
if len(sitter_offers) == 0:
update_client(f'there\'s more than one booking on offer, so I\'m confused!')
return f'Sorry, {sitter_name.title()}, there are no pending gigs.'
elif len(sitter_offers) > 1:
return f'I\'m not sure which offer you\'re responding to!'
offer = sitter_offers[0]
booking = bookings[offer]
if body not in ['yes', 'no', 'n', 'y']:
return f'Hm, I\'m not sure what you meant, {sitter_name.title()}. Please write "yes" or "no".'
if body in ['yes', 'y']:
booking_string = make_booking_string(*offer)
if any(booking['offered'][sitter_] == 'yes'
for sitter_ in booking['offered'].keys()):
return f'Sorry, {sitter_name.title()}, it looks like {booking_string} is already booked.'
booking['offered'][sitter_name] = 'yes'
persist_bookings()
update_client(f'{sitter_name.title()} agreed to babysit on {booking_string}!')
return f'Awesome, {sitter_name.title()}! See you on {booking_string}.'
booking['offered'][sitter_name] = 'no'
persist_bookings()
return f'Okay, no problem, {sitter_name.title()}! Next time.'
def make_booking_string(start_datetime: datetime.datetime, end_time: datetime.time) -> str:
start_time_and_date_string = start_datetime.strftime('%-m/%-d from %-I:%M%p')
end_time_string = end_time.strftime('%-I:%M%p')
return f'{start_time_and_date_string} to {end_time_string}'
def book_forever():
while True:
sitters_, bookings_ = load_from_pickle('sitters'), load_from_pickle('bookings')
if sitters_ and bookings_:
for booking_start_and_end, offered_dict in bookings_.items():
booking = bookings_[booking_start_and_end]
offers = booking['offered']
if any(v == 'yes' for k, v in offers.items()):
continue
if len(sitters_) == len(offers):
continue
booking_string = make_booking_string(*booking_start_and_end)
for sitter_name, sitter_dict in sitters_.items():
if sitter_name not in offers:
offer_booking(sitter_dict, booking_string)
offers[sitter_name] = datetime.datetime.now()
update_client(
f'Okay, I offered {booking_string} to {sitter_name.title()}.')
pprint(bookings_)
persist_bookings(bookings_)
# time.sleep(60)
time.sleep(5)
def offer_booking(sitter_dict: dict, booking_string: str) -> None:
message = f'{sitter_dict["name"].title()}, are you available to babysit on {booking_string}?'
twilio_client.api.account.messages.create(to=sitter_dict['num'],
from_=BOT_NUM,
body=message)
def update_client(string: str) -> None:
twilio_client.api.account.messages.create(to=MY_CELL, from_=BOT_NUM, body=string)
def has_phone_num(string):
return len([char for char in string if char.isnumeric()]) == 10
def request_booking(body: str) -> Tuple[datetime.datetime, datetime.time]:
session_start_datetime, session_end_time = parse_booking_request(body)
global bookings
bookings = load_from_pickle('bookings')
if bookings:
raise TheresAlreadyAnActiveBooking
bookings[(session_start_datetime, session_end_time)] = {'offered': dict()}
persist_bookings()
return session_start_datetime, session_end_time
def parse_booking_request(body: str) -> Tuple[datetime.datetime, datetime.time]:
start_string, end_string = body.split(' to ')
session_start_datetime = cal.parseDT(start_string)[0]
session_end_time = datetime.time(cal.parse(end_string)[0].tm_hour)
return session_start_datetime, session_end_time
def add_sitter(body: str) -> Tuple[str, str]:
name, *num_parts = body.split(' ')
num_only = ''.join(char
for num in num_parts
for char in num if char.isnumeric())
lowercase_name = name.lower()
assert len(num_only) == 10
phone_number = f'{COUNTRY_CODE}{num_only}'
sitters[lowercase_name] = {'num': phone_number,
'name': lowercase_name}
persist_sitters()
return name, phone_number
def remove_sitter(body: str) -> str:
sitter_first_name = body.split(' ')[1]
sitter = sitters.get(sitter_first_name)
if sitter is None:
raise KeyError
del sitters[sitter_first_name]
persist_sitters()
return sitter_first_name
def persist_sitters():
pickle.dump(sitters, open('sitters.p', 'wb'))
def persist_bookings(bookings_: dict = None):
pickle.dump(bookings_ if bookings_ is not None else bookings, open('bookings.p', 'wb'))
if __name__ == '__main__':
update_client('Hi, this is Babysitter Bot, on the job! Send me a date with time range and '
'I\'ll try to book one of our sitters!')
if not sitters:
update_client('Please add at least one babysitter.')
p = Process(target=book_forever)
p.start()
app.run(debug=True, port=8000, use_reloader=False)
p.join()

View File

@@ -4,19 +4,19 @@ from flask import Flask, request
from twilio.rest import Client as TwilioClient
from twilio.twiml.messaging_response import MessagingResponse
twilio_client = TwilioClient(os.getenv('TWILIO_SID'), os.getenv('TWILIO_TOKEN'))
twilio_client = TwilioClient(os.getenv("TWILIO_SID"), os.getenv("TWILIO_TOKEN"))
app = Flask(__name__)
app.config.from_object(__name__)
@app.route('/bot', methods=['POST'])
@app.route("/bot", methods=["POST"])
def bot():
from_ = request.values.get('From')
body = request.values.get('Body').lower()
body = request.values.get("Body").lower()
resp = MessagingResponse()
resp.message(f'ok, you said {body}.')
resp.message(f"ok, you said {body}.")
return str(resp)
if __name__ == '__main__':
app.run(debug=True, port=8000)
if __name__ == "__main__":
app.run(debug=True, port=8000)