Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
pizza-bot/app.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
235 lines (208 sloc)
11.5 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests, os, json | |
from uuid import uuid4 | |
from flask import Flask, request, session | |
from dotenv import load_dotenv | |
from twilio import twiml | |
from twilio.twiml.messaging_response import MessagingResponse | |
from pprint import pprint | |
from utils import Drink, Order, Pizza | |
load_dotenv() | |
with open("db.json", "w") as db: | |
db.close() | |
app = Flask(__name__) | |
googleApiKey = os.getenv('GOOGLE_API_KEY') | |
# gmaps = googlemaps.Client(key=googleApiKey) | |
secret_key = str(uuid4()) | |
app.secret_key = secret_key | |
def printMenuToUser(twilResp: MessagingResponse): | |
twilResp.message("1 - Pizza") | |
twilResp.message("2 - Soft Drinks") | |
def cartCleanReplace(item: str): | |
conditions = {'1': '{','2': '}', '3': '\\', '4':'"', '5':'[', | |
'6':'{', '7':'}', '8':']', '9': ':', '10': ' '} | |
for _, value in conditions.items(): | |
item = item.replace(value, '') | |
return item | |
def createUser(): | |
if 'user' not in session: | |
session['user'] = str(uuid4()) | |
def printPizzaToppings(twilResp: MessagingResponse): | |
twilResp.message("1 - Cheese") | |
twilResp.message("2 - Pepperoni") | |
twilResp.message("3 - Sausage") | |
twilResp.message("4 - Bacon") | |
def printDrinksMenu(twilResp: MessagingResponse): | |
twilResp.message("1 - Coke") | |
twilResp.message("2 - Fanta") | |
twilResp.message("3 - Sprite") | |
# The main endpoint where messages arrive | |
@app.route('/', methods=['POST']) | |
def pizza(): | |
incoming_msg = request.values.get('Body', '') | |
resp = MessagingResponse() | |
msg = resp.message() | |
responded = False | |
if 'exit' == incoming_msg: | |
if 'user' in session: | |
Order.deleteFromStore(session['user']) | |
session.clear() | |
msg.body("Your order has been cancelled. Thank you for trying out The Pizza Bot and have a good day!") | |
responded = True | |
elif 'menu' == incoming_msg: | |
msg.body("Here is the menu for the day: ") | |
printMenuToUser(resp) | |
responded = True | |
elif 'pizza' == incoming_msg: | |
# return a pizza quote, ask for user address and create session for user | |
session.clear() | |
createUser() | |
msg.body('Pizza party coming right up! Please enter your address to view the closest restaurants delivering pizza.') | |
responded = True | |
elif 'done' == incoming_msg: | |
msg.body("Please type in the phone number you can be reached at: ") | |
session['orderStatus'] = 'complete' | |
responded = True | |
else: | |
if 'user' in session: | |
# user enters address | |
if 'location' not in session: | |
location = str(incoming_msg) | |
# save the location of the user in order | |
session['location'] = location | |
# convert incoming location to http-request friendly | |
prepped_location = location.replace(' ', '+') | |
# grab coordinates of user location | |
r = requests.get(f'https://maps.googleapis.com/maps/api/geocode/json?address={prepped_location}&key={googleApiKey}') | |
if r.status_code == 200: | |
geo_details = r.json()['results'][0]['geometry']['location'] | |
latitude = geo_details['lat'] | |
longitude = geo_details['lng'] | |
# check for available pizza places within 5km | |
r = requests.get(f'https://maps.googleapis.com/maps/api/place/nearbysearch/json?location={latitude},{longitude}&rankby=distance&keyword=pizza&key={googleApiKey}') | |
if r.status_code == 200: | |
results = r.json()['results'] | |
if results == []: | |
resp.message("We're so sorry. There are no available locations close to you.") | |
else: | |
# pick top 3 pizza locations | |
pprint(results) | |
places = [place for place in results if ('opening_hours' in place) and (place['opening_hours']['open_now'] or place['business_status'] == 'OPERATIONAL') and results.index(place) < 3] | |
if places != []: | |
msg.body("Here are the 3 closest available locations. Please select a location using the number in front of the location: ") | |
count = 1 | |
for place in places: | |
message = f"{count} - {place['name']} - {place['vicinity']}" | |
resp.message(message) | |
count += 1 | |
order = Order(id=session['user'], orderLocation=location, possible_locations=places, phone_no=None) | |
order.store() | |
session['places'] = True | |
else: | |
resp.message("There are no open locations within 5km of you.") | |
else: | |
msg.body('Could not find your location. Please try again.') | |
responded = True | |
else: | |
# user picks an order location | |
if 'orderLocation' not in session: | |
# grab user location choice and add to order | |
location_choice = int(incoming_msg) | |
order_dict = Order.getOrder(session['user']) | |
possible_locations = order_dict['possible_locations'] | |
order_dict['address'] = session['location'] | |
# save user order location choice to store | |
selected_location = possible_locations[location_choice - 1] | |
order_dict['orderLocation'] = selected_location | |
order = Order.orderFromStore(order_dict=order_dict) | |
order.store() | |
session['orderLocation'] = True | |
# respond to user | |
msg.body(f'You have selected {selected_location["name"]} and your location has been saved') | |
msg.body("You can type menu to print the menu for the day") | |
printMenuToUser(twilResp=resp) | |
responded = True | |
else: | |
if 'orderStatus' in session: | |
order_dict = Order.getOrder(session['user']) | |
order_dict['phone_no'] = incoming_msg | |
msg.body("Here is your cart: ") | |
for item in order_dict['cart']: | |
if "drink" in item: | |
drinks = cartCleanReplace(item['drink'].replace("choice", "")) | |
resp.message(f"Drinks - {drinks}") | |
if "pizza" in item: | |
toppings = cartCleanReplace(item['pizza'].replace("toppings", "")) | |
resp.message(f"Pizza with - {toppings}") | |
order = Order.orderFromStore(order_dict=order_dict) | |
order.completeOrder() | |
order.store() | |
resp.message("Your order has been succesfully submitted and will be delivered shortly." + | |
" Thank you for trying out The Pizza Bot!") | |
session.clear() | |
responded = True | |
else: | |
val = '' | |
try: | |
val = int(str(incoming_msg)) | |
except ValueError as err: | |
val = str(incoming_msg).replace(',', ' ').strip().split(" ") | |
for value in val: | |
try: | |
value = int(value) | |
except ValueError as err: | |
val.remove(value) | |
val = [int(value) for value in val] | |
if 'pizza' in session: | |
order_pizza = Pizza(toppings=val) | |
order_dict = Order.getOrder(id=session['user']) | |
order = Order.orderFromStore(order_dict=order_dict) | |
pizza_dict = { | |
'pizza': (json.dumps(order_pizza.__dict__)) | |
} | |
order.addToCart(pizza_dict) | |
order.store() | |
msg.body(f"Your pizza has been added to your cart!") | |
session.pop('pizza') | |
resp.message("Remember you can type 'done' to complete your order! You can text 'menu' to see the menu again!") | |
printMenuToUser(twilResp=resp) | |
responded = True | |
elif 'drinks' in session: | |
order_drink = Drink(choice=val) | |
order_dict = Order.getOrder(id=session['user']) | |
order = Order.orderFromStore(order_dict=order_dict) | |
drink_dict = { | |
'drink': (json.dumps(order_drink.__dict__)) | |
} | |
order.addToCart(drink_dict) | |
order.store() | |
msg.body(f"Your drink(s) has/have been added to your cart!") | |
session.pop('drinks') | |
resp.message("Remember you can type 'done' to complete your order! You can text 'menu' to see the menu again!") | |
printMenuToUser(twilResp=resp) | |
responded = True | |
else: | |
if int(incoming_msg) == 1: | |
session['pizza'] = True | |
msg.body("You have selected Pizza. Please select the toppings you would like separated by commas. " + | |
"For example, for extra cheese and pepperoni, text - 1, 2") | |
printPizzaToppings(twilResp=resp) | |
responded = True | |
if int(incoming_msg) == 2: | |
session['drinks'] = True | |
msg.body("You have selected Drinks. They all come in 75cl bottles." + | |
" Please select the drink you would like separated by commas. " + | |
" For example, for Coke and Fanta, text - 1, 2") | |
printDrinksMenu(twilResp=resp) | |
responded = True | |
if not responded: | |
if 'user' in session: | |
msg.body("Seems like an invalid command was used! Please follow the last prompt") | |
else: | |
msg.body("Hi there! I'm The Pizza Bot! I'm here to help you order delicious pizza! " + | |
"You can begin an order with the command: pizza. " + | |
"You can complete an order with the command: done. " + | |
"You can see my available items on the menu at any time with the command: menu. " + | |
"You can cancel the process at any time by texting the command: exit.") | |
return str(resp) | |
if __name__ == '__main__': | |
app.run(debug=False) |