from flask import Flask, render_template_string, request, jsonify from simple_salesforce import Salesforce import logging from tempfile import NamedTemporaryFile import os import re import traceback import ffmpeg import speech_recognition as sr from werkzeug.exceptions import BadRequest from datetime import datetime from word2number import w2n # Import word-to-number conversion library app = Flask(__name__) logging.basicConfig(level=logging.INFO) # Salesforce connection setup sf = Salesforce( username='diggavalli98@gmail.com', password='Sati@1020', security_token='sSSjyhInIsUohKpG8sHzty2q', consumer_key='3MVG9WVXk15qiz1JbtW1tT9a7Wnkos2RuGamw6p1lC5uPescT5NB2nPygpo6rQ87K1T.zBEn.wR.A6JdgHnIU', consumer_secret='A75C6B7801D5D20BED0E46631CF58C4F7FF28E4DAF442FE667553D29C35C0451' ) # Global variables cart = [] # To store items, quantities, prices, and add-ons current_category = None awaiting_preference = True awaiting_quantity = False user_email = None # Will be set later once the user provides it awaiting_item_selection = False # Flag to know when to ask for item selection user_name = None # Will be set once the user provides their name # Function to fetch menu items from Salesforce based on the category filter def get_menu_items(category): category_filter = '' if category == 'Veg': category_filter = 'Veg' elif category == 'Non-Veg': category_filter = 'Non veg' elif category == 'All': category_filter = '' # No filter for 'All' query = f""" SELECT Id, Name, Price__c, Image1__c, Veg_NonVeg__c, Section__c FROM Menu_Item__c WHERE Veg_NonVeg__c = '{category_filter}' OR Veg_NonVeg__c = 'both' """ if category_filter else """ SELECT Id, Name, Price__c, Image1__c, Veg_NonVeg__c, Section__c FROM Menu_Item__c """ result = sf.query_all(query) return result['records'] # Function to save order to Salesforce def save_order_to_salesforce(cart, user_email, total_amount): order_items = ", ".join([f"{item['Name']} x {item['Quantity']}" for item in cart]) order = { 'Customer_Email__c': user_email, 'Order_Date_Time__c': datetime.now(), 'Order_Items__c': order_items, 'Total_Amount__c': total_amount, 'Status__c': 'Pending' } order_record = sf.Order__c.create(order) return order_record # HTML Template for Frontend html_code = """ AI Dining Assistant

AI Dining Assistant

Press the mic button to start...
""" @app.route("/") def index(): return render_template_string(html_code) @app.route("/process-audio", methods=["POST"]) def process_audio(): global awaiting_preference, current_category, awaiting_quantity, cart, awaiting_item_selection, user_name try: audio_file = request.files.get("audio") if not audio_file: raise BadRequest("No audio file provided.") temp_file = NamedTemporaryFile(delete=False, suffix=".webm") audio_file.save(temp_file.name) if os.path.getsize(temp_file.name) == 0: raise BadRequest("Uploaded audio file is empty.") converted_file = NamedTemporaryFile(delete=False, suffix=".wav") ffmpeg.input(temp_file.name).output( converted_file.name, acodec="pcm_s16le", ac=1, ar="16000", loglevel='error' ).run(overwrite_output=True) recognizer = sr.Recognizer() with sr.AudioFile(converted_file.name) as source: recognizer.adjust_for_ambient_noise(source, duration=1) audio_data = recognizer.record(source, duration=10) try: command = recognizer.recognize_google(audio_data) logging.info(f"Recognized command: {command}") response = process_command(command) except sr.UnknownValueError: response = "Sorry, I couldn't understand your command. Could you please repeat?" except sr.RequestError as e: response = f"Error with the speech recognition service: {e}" return jsonify({"response": response}) except BadRequest as br: return jsonify({"response": f"Bad Request: {str(br)}"}), 400 except Exception as e: return jsonify({"response": f"An error occurred: {str(e)}"}), 500 finally: os.unlink(temp_file.name) os.unlink(converted_file.name) # Updated Email Handling def process_command(command): global awaiting_preference, current_category, awaiting_quantity, cart, awaiting_item_selection, user_email, user_name logging.info(f"Processing command: {command}") # Indentation fixed try: # Step 1: Handle user name input (personalize the greeting) if user_name is None and "my name is" in command: user_name = command.replace("my name is", "").strip() return jsonify({"response": f"Hello {user_name}! Nice to meet you. Please choose your preference: Veg, Non-Veg, or All."}) # Additional logic continues... except Exception as e: logging.error(f"An error occurred while processing the command: {str(e)}") return jsonify({"response": "Sorry, there was an error processing your request."}), 500 if awaiting_preference: if "veg" in command: current_category = 'Veg' elif "non-veg" in command: current_category = 'Non-Veg' elif "all" in command: current_category = 'All' else: return jsonify({"response": "I didn't catch your preference. Please choose Veg, Non-Veg, or All."}) awaiting_preference = False awaiting_item_selection = True return jsonify({"response": f"Great! You've selected {current_category}. What would you like to order?"}) if awaiting_item_selection: menu_items = get_menu_items(current_category) selected_item = next((item for item in menu_items if item['Name'].lower() in command), None) if selected_item: cart.append({"Name": selected_item['Name'], "Price__c": selected_item['Price__c'], "Quantity": 0}) awaiting_item_selection = False awaiting_quantity = True return jsonify({"response": f"You selected {selected_item['Name']}. How many would you like to order?"}) return jsonify({"response": "I didn't catch that. Please say the name of the item you want to order."}) if awaiting_quantity: try: quantity = int(command) if quantity > 0: cart[-1]["Quantity"] = quantity awaiting_quantity = False return jsonify({"response": f"Quantity set to {quantity}. Please provide your email to complete the order."}) else: return jsonify({"response": "Quantity must be greater than zero."}) except ValueError: return jsonify({"response": "Please provide a valid number for quantity."}) if "my email is" in command: email_part = command.replace("my email is", "").strip() email_command = email_part.replace(' at ', '@').replace(' dot ', '.').replace(' ', '') logging.info(f"Processed email command: {email_command}") email_pattern = r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$" match = re.match(email_pattern, email_command) if match: user_email = match.group(0) return jsonify({"response": f"Got it! Your email is {user_email}. Now, your order will be processed. Would you like to confirm your order?"}) else: return jsonify({"response": "Sorry, that doesn't look like a valid email. Can you please provide it again?"}) if "final order" in command or "confirm my order" in command or "place the order" in command or "confirm order" in command: return place_order() return jsonify({"response": "I'm not sure what you're trying to do. Can you please repeat?"}) except Exception as e: logging.error(f"An error occurred while processing the command: {str(e)}") logging.error(f"Stack Trace: {traceback.format_exc()}") return jsonify({"response": "Sorry, there was an error processing your request."}), 500 def place_order(): global cart, user_email, user_name try: total_amount = sum([item['Price__c'] * item['Quantity'] for item in cart]) order_record = save_order_to_salesforce(cart, user_email, total_amount) order_query = f""" SELECT Id, Name, Customer_Email__c FROM Order__c WHERE Customer_Email__c = '{user_email}' AND Name = '{user_name}' ORDER BY CreatedDate DESC LIMIT 1 """ order_result = sf.query_all(order_query) if not order_result['records']: return jsonify({"response": "Failed to retrieve the placed order. Please try again."}) order_id = order_result['records'][0]['Id'] for item in cart: order_item = { 'Order__c': order_id, 'Item_Name__c': item['Name'], 'Quantity__c': item['Quantity'], 'Price__c': item['Price__c'], } sf.Order_Item__c.create(order_item) cart = [] # Clear the cart return jsonify({"response": f"Order placed successfully! Total amount: ₹{total_amount}"}) except Exception as e: return jsonify({"response": f"An error occurred: {str(e)}"}), 500 if __name__ == "__main__": app.run(host="0.0.0.0", port=7860)