Skip to content
This repository has been archived by the owner on Jan 9, 2023. It is now read-only.

Commit

Permalink
Merge pull request #22 from rauldpm/14_email_main
Browse files Browse the repository at this point in the history
Add email reservation procedure
  • Loading branch information
Raul Del Pozo Moreno authored Jul 25, 2022
2 parents c169b2d + a345a00 commit 8b5419f
Show file tree
Hide file tree
Showing 25 changed files with 1,996 additions and 1,316 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,4 @@ results
.keras
.config
logs
values.env
secrets/*
5 changes: 4 additions & 1 deletion Docker/actions/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ WORKDIR /app

RUN apt-get update
RUN apt-get install -y locales

RUN locale-gen es_ES
RUN locale-gen es_ES.utf8

# Install python requirements
COPY Docker/actions/requirements.txt requirements.txt
RUN pip install --upgrade pip
RUN pip install --verbose -r requirements.txt

# Copy email secrets
COPY secrets/email_secrets.env /app/secrets/

EXPOSE 5055
USER 1001
3 changes: 2 additions & 1 deletion Docker/actions/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
Unidecode
Unidecode
python-decouple
3 changes: 2 additions & 1 deletion Docker/server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ USER root
# Copy proyect files
COPY actions/* /app/actions/
COPY data/* /app/data/
COPY config.yml credentials.yml domain.yml endpoints.yml values.env /app/
COPY secrets/telegram_secrets.env /app/secrets/
COPY config.yml credentials.yml domain.yml endpoints.yml /app/
COPY Docker/server/entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
WORKDIR '/app'
Expand Down
2 changes: 1 addition & 1 deletion Docker/server/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/bin/bash

# Set secrets
source /app/values.env
source /app/secrets/telegram_secrets.env

# Run rasa
rasa run -m /app/models --enable-api --cors * --debug --endpoints endpoints.yml --log-file logs/rasa.log --debug
38 changes: 37 additions & 1 deletion actions/clases/auxiliar.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@

from rasa_sdk.interfaces import Action
import pathlib
from os import path
import json
Expand Down Expand Up @@ -56,3 +56,39 @@ def get_horas(self):

def get_data_path(self):
return self.data_path

class Opciones(Action):
def name(self):
return "Opciones"

def run(self, dispatcher, tracker, domain):
print("Opciones")

buttons = []
buttons = [
{'title': 'Opciones', 'payload': '/opciones'},
{'title': 'Horario', 'payload': '/horario'},
{'title': 'Consultar carta', 'payload': '/menu_completo'}
]

if tracker.get_slot("first_name_set"):
buttons.append({"title": "Olvidame", "payload": "/identificar_borrar"})
else:
buttons.append({"title": "Identificarme", "payload": "/identificar"})

if tracker.get_slot("menu_establecido"):
buttons.append({"title": "Borrar menu", "payload": "/menu_borra_todo"})
buttons.append({"title": "Borrar plato", "payload": "/menu_borra_plato"})
buttons.append({"title": "Consultar mi menu", "payload": "/menu_usuario"})
else:
buttons.append({"title": "Establecer menu", "payload": "/establecer_menu"})

if tracker.get_slot("reserva_dia") or tracker.get_slot("reserva_hora") or tracker.get_slot("reserva_comensales") or tracker.get_slot("reserva_completa"):
buttons.append({"title": "Borrar reserva", "payload": "/reserva_borrar_mesa"})
buttons.append({"title": "Finalizar reserva", "payload": "/finalizar_reserva"})
buttons.append({"title": "Consultar mi reserva", "payload": "/reserva_usuario"})
else:
buttons.append({"title": "Realizar reserva de mesa", "payload": "/reservar"})

dispatcher.utter_message(text=f'Estas son las opciones que puedes realizar ahora', buttons=buttons, button_type="vertical")
return ""
66 changes: 66 additions & 0 deletions actions/clases/email.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib
import ssl
from decouple import Config, RepositoryEnv

# -----------------------------------------
DOTENV_FILE = 'secrets/email_secrets.env'
env_config = Config(RepositoryEnv(DOTENV_FILE))
# -----------------------------------------

class Email():

def __init__(self):
self.port = int(env_config.get("EMAIL_SERVER_PORT"))
self.server = env_config.get("EMAIL_SERVER_SMTP")
self.sender = env_config.get("EMAIL_SENDER")
self.password = env_config.get("EMAIL_APP_PASSWORD")

def send_email(self, recipient, message, subject):
msg = MIMEMultipart()
msg['From'] = self.sender
msg['To'] = recipient
msg['Subject'] = subject
msg.attach(MIMEText(message, "plain"))
text = msg.as_string()
SSLcontext = ssl.create_default_context()

with smtplib.SMTP(self.server, self.port) as server:
server.starttls(context=SSLcontext)
server.login(self.sender, self.password)
server.sendmail(self.sender, recipient, text)

def send_email_code(self, recipient, code, name):

message = "Hello " + name + "!\n\n"
message += "Your reservation code is: " + code
subject = "Restaurant reservation code"
self.send_email(recipient, message, subject)


def send_email_message(self, recipient, reserva_array, menu_array):

message = "Hello " + reserva_array[4] + "!\n\n"
message += "The details of your reservation are:\n\n"
message += "- Day: " + reserva_array[0] + "\n"
message += "- Hour: " + reserva_array[1] + "\n"
message += "- Table: " + str(reserva_array[2]) + "\n"
message += "- Name: " + reserva_array[4] + "\n"
message += "- Diners: " + str(reserva_array[3]) + "\n\n"
if len(menu_array) > 0:
message += "Your menu is composed of:\n\n"
if menu_array[0] is not None:
message += "- Starter: " + menu_array[0] + "\n"
if menu_array[1] is not None:
message += "- Meat: " + menu_array[1] + "\n"
if menu_array[2] is not None:
message += "- Fish: " + menu_array[2] + "\n"
if menu_array[3] is not None:
message += "- Dessert: " + menu_array[3] + "\n"
if menu_array[4] is not None:
message += "- Drink: " + menu_array[4] + "\n"


subject = "Restaurant reservation resume"
self.send_email(recipient, message, subject)
17 changes: 15 additions & 2 deletions actions/clases/identificacion.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ def run(self, dispatcher, tracker, domain):
print("IdentificarBorrarUsername")
dispatcher.utter_message(
text=f'He borrado tu nombre de usuario, recuerda que es necesario identificarte para terminar el proceso de reserva.')
return [SlotSet("first_name", None), SlotSet("first_name_save", None), SlotSet("first_name_set", None), SlotSet("name_spelled_correctly", None)]
return [SlotSet("first_name", None), SlotSet("first_name_save", None), SlotSet("first_name_set", None), SlotSet("name_spelled_correctly", None), SlotSet("reserva_completa", False)]


class ValidateNameForm(FormValidationAction):
Expand All @@ -47,6 +47,9 @@ async def extract_name_spelled_correctly(
print("extract_name_spelled_correctly")
first_name = tracker.get_slot("first_name")
intent = tracker.get_intent_of_latest_message()
first_name_set = tracker.get_slot("first_name_set")
if first_name_set:
return {}
if intent == "affirm":
first_name = tracker.get_slot("first_name_save")
if first_name != "/repetir_nombre":
Expand All @@ -63,6 +66,10 @@ def validate_name_spelled_correctly(
) -> Dict[Text, Any]:
print("validate_name_spelled_correctly")

first_name_set = tracker.get_slot("first_name_set")
if first_name_set:
return {}

if tracker.get_intent_of_latest_message() == "stop":
return {"requested_slot": None, "first_name": None, "name_spelled_correctly": None, "first_name_set": None}

Expand Down Expand Up @@ -120,5 +127,11 @@ def validate_first_name(
text=f"El nombre no cumple con los requisitos (minimo 3 letras y maximo 11)")
return {"first_name": None, "name_spelled_correctly": False}
else:
return {"first_name": slot_value, "first_name_set": True}
reserva_dia = tracker.get_slot("reserva_dia")
reserva_hora = tracker.get_slot("reserva_hora")
reserva_comensales = tracker.get_slot("reserva_comensales")
if reserva_dia is not None and reserva_hora is not None and reserva_comensales is not None:
return {"first_name": slot_value, "first_name_set": True, "reserva_completa": True}

return {"first_name": slot_value, "first_name_set": True, "reserva_completa": False}
return {"first_name": None, "name_spelled_correctly": False}
57 changes: 57 additions & 0 deletions actions/clases/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,63 @@ def run(self, dispatcher, tracker, domain):
text=f'No se ha establecido una categoria')


class MenuGetBotones(Action):
def name(self):
return 'MenuGetBotones'

def get_submenu_botones(Action, tipo):
data = auxiliar.get_data_generic(DATA_PATH+"/data/menu/"+tipo+".json")
buttons = []
for it in data[tipo]:
buttons.append({"title": "{}".format(
it['nombre']), "payload": "{}".format(it['id'])})
return buttons

def run(self, dispatcher, tracker, domain):
print("MenuGetBotones")
menu_plato_categoria = tracker.get_slot("menu_plato_categoria")


if menu_plato_categoria is not None:

menu_plato_categoria = menu_plato_categoria.lower()
for it in CATEGORIA_MENU:
if menu_plato_categoria in it:
menu_plato_categoria = it
break
if menu_plato_categoria in CATEGORIA_MENU:
buttons = self.get_submenu_botones(menu_plato_categoria)
dispatcher.utter_message(text=f'Selecciona el plato que desees', buttons=buttons)
return ""
else:
dispatcher.utter_message(text=f'Esa categoria no existe.')
return [SlotSet("menu_plato_categoria", None)]
else:
dispatcher.utter_message(
text=f'No se ha establecido una categoria')


class MenuCheckCategoria(Action):
def name(self):
return 'MenuCheckCategoria'

def run(self, dispatcher, tracker, domain):
print("MenuCheckCategoria")
menu_plato_categoria = tracker.get_slot("menu_plato_categoria")
if menu_plato_categoria is not None:
for it in CATEGORIA_MENU:
if menu_plato_categoria in it:
menu_plato_categoria = it
break
if menu_plato_categoria in CATEGORIA_MENU:
return [SlotSet("menu_plato_categoria", menu_plato_categoria)]
else:
return [SlotSet("menu_plato_categoria", None)]

else:
return ""


class MenuGetCategoriasButtons(Action):
def name(self):
return 'MenuGetCategoriasButtons'
Expand Down
Loading

0 comments on commit 8b5419f

Please sign in to comment.