added some more steps for the blog post
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
.*sw*
|
||||
.DS_Store
|
||||
*~
|
||||
.idea/
|
||||
|
||||
14
.idea/babysitter_bot.iml
generated
14
.idea/babysitter_bot.iml
generated
@@ -1,14 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="PYTHON_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="jdk" jdkName="Python 3.6.0 virtualenv at ~/.pyenv/versions/babysitter_bot" jdkType="Python SDK" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
<component name="TemplatesService">
|
||||
<option name="TEMPLATE_CONFIGURATION" value="Jinja2" />
|
||||
</component>
|
||||
<component name="TestRunnerService">
|
||||
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
|
||||
</component>
|
||||
</module>
|
||||
43
.idea/inspectionProfiles/Project_Default.xml
generated
43
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -1,43 +0,0 @@
|
||||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="PyPackageRequirementsInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredPackages">
|
||||
<value>
|
||||
<list size="18">
|
||||
<item index="0" class="java.lang.String" itemvalue="Werkzeug" />
|
||||
<item index="1" class="java.lang.String" itemvalue="wsgiref" />
|
||||
<item index="2" class="java.lang.String" itemvalue="MarkupSafe" />
|
||||
<item index="3" class="java.lang.String" itemvalue="requests" />
|
||||
<item index="4" class="java.lang.String" itemvalue="itsdangerous" />
|
||||
<item index="5" class="java.lang.String" itemvalue="Jinja2" />
|
||||
<item index="6" class="java.lang.String" itemvalue="click" />
|
||||
<item index="7" class="java.lang.String" itemvalue="Flask" />
|
||||
<item index="8" class="java.lang.String" itemvalue="plaid-python" />
|
||||
<item index="9" class="java.lang.String" itemvalue="asn1crypto" />
|
||||
<item index="10" class="java.lang.String" itemvalue="pyOpenSSL" />
|
||||
<item index="11" class="java.lang.String" itemvalue="cffi" />
|
||||
<item index="12" class="java.lang.String" itemvalue="cryptography" />
|
||||
<item index="13" class="java.lang.String" itemvalue="packaging" />
|
||||
<item index="14" class="java.lang.String" itemvalue="pycparser" />
|
||||
<item index="15" class="java.lang.String" itemvalue="pyparsing" />
|
||||
<item index="16" class="java.lang.String" itemvalue="twilio" />
|
||||
<item index="17" class="java.lang.String" itemvalue="idna" />
|
||||
</list>
|
||||
</value>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="PyUnresolvedReferencesInspection" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="ignoredIdentifiers">
|
||||
<list>
|
||||
<option value="plaid.Client" />
|
||||
</list>
|
||||
</option>
|
||||
</inspection_tool>
|
||||
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
|
||||
<option name="processCode" value="true" />
|
||||
<option name="processLiterals" value="true" />
|
||||
<option name="processComments" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
||||
7
.idea/misc.xml
generated
7
.idea/misc.xml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="PreferredVcsStorage">
|
||||
<preferredVcsName>ApexVCS</preferredVcsName>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.6.0 virtualenv at ~/.pyenv/versions/babysitter_bot" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
8
.idea/modules.xml
generated
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/babysitter_bot.iml" filepath="$PROJECT_DIR$/.idea/babysitter_bot.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
6
.idea/vcs.xml
generated
@@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
185
.idea/workspace.xml
generated
185
.idea/workspace.xml
generated
@@ -1,185 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="d62c162e-b344-4d79-986f-e8c09fbec6ca" name="Default" comment="">
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/requirements.txt" afterPath="$PROJECT_DIR$/requirements.txt" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/sitter_bot.py" afterPath="$PROJECT_DIR$/sitter_bot.py" />
|
||||
</list>
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="TRACKING_ENABLED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileColors">
|
||||
<fileColor scope="Non-Project Files (Material Default)" color="2E3C43" />
|
||||
<fileColor scope="Non-Project Files (Material Darker)" color="323232" />
|
||||
<fileColor scope="Non-Project Files (Material Lighter)" color="eae8e8" />
|
||||
<fileColor scope="Non-Project Files (Material Palenight)" color="2f2e43" />
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf>
|
||||
<file leaf-file-name="sitter_bot.py" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/sitter_bot.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="189">
|
||||
<caret line="9" column="80" lean-forward="false" selection-start-line="6" selection-start-column="0" selection-end-line="9" selection-end-column="80" />
|
||||
<folding>
|
||||
<element signature="e#0#15#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/sitter_bot.py" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||
<component name="JsGulpfileManager">
|
||||
<detection-done>true</detection-done>
|
||||
<sorting>DEFINITION_ORDER</sorting>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="x" value="90" />
|
||||
<option name="width" value="986" />
|
||||
<option name="height" value="1920" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||
<flattenPackages />
|
||||
<showMembers />
|
||||
<showModules />
|
||||
<showLibraryContents />
|
||||
<hideEmptyPackages />
|
||||
<abbreviatePackageNames />
|
||||
<autoscrollToSource />
|
||||
<autoscrollFromSource />
|
||||
<sortByType />
|
||||
<manualOrder />
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="Scope" />
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="babysitter_bot" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="babysitter_bot" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scratches" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="settings.editor.selected.configurable" value="com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable" />
|
||||
<property name="WebServerToolWindowFactoryState" value="false" />
|
||||
<property name="last_opened_file_path" value="$USER_HOME$/.pyenv/versions/babysitter_bot/bin/python3.6" />
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager" selected="Python.babysitter_bot">
|
||||
<configuration name="babysitter_bot" type="PythonConfigurationType" factoryName="Python" singleton="true">
|
||||
<option name="INTERPRETER_OPTIONS" value="" />
|
||||
<option name="PARENT_ENVS" value="true" />
|
||||
<envs>
|
||||
<env name="PYTHONUNBUFFERED" value="1" />
|
||||
</envs>
|
||||
<option name="SDK_HOME" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="" />
|
||||
<option name="IS_MODULE_SDK" value="false" />
|
||||
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||
<module name="babysitter_bot" />
|
||||
<EXTENSION ID="PythonCoverageRunConfigurationExtension" enabled="false" sample_coverage="true" runner="coverage.py" />
|
||||
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/sitter_bot.py" />
|
||||
<option name="PARAMETERS" value="" />
|
||||
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||
<option name="EMULATE_TERMINAL" value="false" />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="ShelveChangesManager" show_recycled="false">
|
||||
<option name="remove_strategy" value="false" />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="d62c162e-b344-4d79-986f-e8c09fbec6ca" name="Default" comment="" />
|
||||
<created>1508950836856</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1508950836856</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="0" y="0" width="1080" height="1920" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Python Console" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.14537036" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32958803" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Data View" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="VcsContentAnnotationSettings">
|
||||
<option name="myLimit" value="2678400000" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager />
|
||||
<watches-manager />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/sitter_bot.py">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="189">
|
||||
<caret line="9" column="80" lean-forward="false" selection-start-line="6" selection-start-column="0" selection-end-line="9" selection-end-column="80" />
|
||||
<folding>
|
||||
<element signature="e#0#15#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
||||
59
basic_sitter_bot.py
Normal file
59
basic_sitter_bot.py
Normal file
@@ -0,0 +1,59 @@
|
||||
import os
|
||||
from typing import Tuple
|
||||
|
||||
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'))
|
||||
|
||||
app = Flask(__name__)
|
||||
app.config.from_object(__name__)
|
||||
|
||||
sitters = {}
|
||||
|
||||
@app.route('/bot', methods=['POST'])
|
||||
def bot():
|
||||
from_ = request.values.get('From')
|
||||
body = request.values.get('Body').lower()
|
||||
response = 'I wasn\'t sure what to do with your input. '
|
||||
|
||||
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}. '
|
||||
print(sitters)
|
||||
|
||||
resp = MessagingResponse()
|
||||
resp.message(response)
|
||||
return str(resp)
|
||||
|
||||
|
||||
def has_phone_num(string):
|
||||
return len([char for char in string if char.isnumeric()]) == 10
|
||||
|
||||
|
||||
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()
|
||||
sitter = sitters.get(lowercase_name)
|
||||
|
||||
assert len(num_only) == 10
|
||||
|
||||
sitters[lowercase_name] = f'+1{num_only}'
|
||||
|
||||
return name, sitters[lowercase_name]
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(debug=True, port=8000)
|
||||
|
||||
74
basic_sitter_bot_with_pickle.py
Normal file
74
basic_sitter_bot_with_pickle.py
Normal file
@@ -0,0 +1,74 @@
|
||||
import os
|
||||
import pickle
|
||||
from typing import Tuple
|
||||
|
||||
from flask import Flask, request
|
||||
from twilio.rest import Client as TwilioClient
|
||||
from twilio.twiml.messaging_response import MessagingResponse
|
||||
|
||||
MY_CELL = os.getenv('MY_CELL')
|
||||
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.route('/bot', methods=['POST'])
|
||||
def bot():
|
||||
from_ = request.values.get('From')
|
||||
body = request.values.get('Body').lower()
|
||||
response = 'I wasn\'t sure what to do with your input. '
|
||||
|
||||
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}. '
|
||||
print(sitters)
|
||||
|
||||
resp = MessagingResponse()
|
||||
resp.message(response)
|
||||
return str(resp)
|
||||
|
||||
|
||||
def has_phone_num(string):
|
||||
return len([char for char in string if char.isnumeric()]) == 10
|
||||
|
||||
|
||||
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()
|
||||
sitter = sitters.get(lowercase_name)
|
||||
|
||||
assert len(num_only) == 10
|
||||
|
||||
sitters[lowercase_name] = f'+1{num_only}'
|
||||
persist_sitters()
|
||||
|
||||
return name, sitters[lowercase_name]
|
||||
|
||||
|
||||
def persist_sitters():
|
||||
pickle.dump(sitters, open('sitters.p', 'wb'))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sitters:
|
||||
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)
|
||||
|
||||
@@ -60,7 +60,7 @@ def bot() -> str:
|
||||
if not sitters:
|
||||
response = f'You don\'t have any sitters yet. {help_add}.'
|
||||
else:
|
||||
sitter_list = 'Your sitters are ' + ', '.join(
|
||||
sitter_list = 'Your sitters are ' + ' and '.join(
|
||||
f'{sitter_name.title()}' for sitter_name in sitters) + '.'
|
||||
response = f'{sitter_list} {help_text}'
|
||||
|
||||
@@ -100,7 +100,7 @@ def bot() -> str:
|
||||
|
||||
|
||||
def has_phone_num(string):
|
||||
return len([char for char in string if char.isnumeric()]) >= 10
|
||||
return len([char for char in string if char.isnumeric()]) == 10
|
||||
|
||||
|
||||
def syndicate_and_book(session_start: datetime.datetime, session_end: datetime.datetime) -> Optional[str]:
|
||||
@@ -111,13 +111,13 @@ def syndicate_and_book(session_start: datetime.datetime, session_end: datetime.d
|
||||
pass
|
||||
|
||||
|
||||
def book_sitter(in_message: str) -> Optional[str]:
|
||||
session_start, session_end = parse_sitter_request(in_message)
|
||||
def book_sitter(body: str) -> Optional[str]:
|
||||
session_start, session_end = parse_sitter_request(body)
|
||||
syndicate_and_book(session_start, session_end)
|
||||
|
||||
|
||||
def add_sitter(in_message: str) -> Tuple[str, str]:
|
||||
name, *num_parts = in_message.split(' ')
|
||||
def add_sitter(body: str) -> Tuple[str, str]:
|
||||
name, *num_parts = body.split(' ')
|
||||
|
||||
num_only = ''.join(char
|
||||
for num in num_parts
|
||||
|
||||
Reference in New Issue
Block a user