Spaces:
Sleeping
Sleeping
| from typing import Dict, List | |
| from fastapi import FastAPI, APIRouter, HTTPException, Request, Response # type: ignore | |
| from fastapi.responses import JSONResponse, RedirectResponse, HTMLResponse # type: ignore | |
| from datetime import datetime, timedelta | |
| from fastapi.templating import Jinja2Templates | |
| from app.dialogflow.services.dialog_service import dialog_service | |
| from utils.format_data_dialog import extra_time_dialogflow, get_weekday_name, find_surrounding_times | |
| from common.external.external_api import api | |
| from app.dialogflow.services.origin_codes import origin_codes, get_origin_id_and_code | |
| from common.response.respone_dialogflow import DialogFlowResponseAPI | |
| router = APIRouter() | |
| templates = Jinja2Templates(directory="templates") | |
| async def search_origin_office(request: Request): | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| raw_departure_city = parameters.get("departure_city", None) | |
| origin_office = parameters.get("origin_office") | |
| departure_city = None | |
| if origin_office and raw_departure_city is None: | |
| departure_city = await dialog_service.get_origin_city_from_office(origin_office) | |
| parameters = { | |
| "departure_city": departure_city | |
| } | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| async def search_destination_office(request: Request): | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| raw_destination_city = parameters.get("destination_city", None) | |
| dest_office = parameters.get("dest_office") | |
| destination_city = None | |
| if dest_office and raw_destination_city is None: | |
| destination_city = await dialog_service.get_destination_city_from_office(dest_office) | |
| parameters = { | |
| "destination_city": destination_city | |
| } | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| async def confirm(request: Request): | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters", {}) if isinstance(session_info.get("parameters"), dict) else {} | |
| raw_date = parameters.get("date") | |
| departure_city = parameters.get("departure_city") | |
| destination_city = parameters.get("destination_city") | |
| origin_office = parameters.get("origin_office") | |
| dest_office = parameters.get("dest_office") | |
| raw_ticket_number = parameters.get("ticket_number") | |
| time = parameters.get("time-select") | |
| time = extra_time_dialogflow(time) | |
| parameters = {} | |
| if isinstance(time, list): | |
| parameters["is_time_ambiguous"] = True | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| ticket_number = int(raw_ticket_number) if raw_ticket_number else 1 | |
| date = dialog_service.to_datetime_from_Dialogflow(raw_date) | |
| date, week_day = get_weekday_name(date) | |
| text = [f"""**Thời gian:** {time} - {date} - {week_day}\n**Số vé:** {ticket_number}"""] | |
| temp = "" | |
| if origin_office and dest_office: | |
| temp = f"""**Điểm đi:** {origin_office}\n**Điểm đến:** {dest_office}\n""" | |
| elif origin_office and destination_city: | |
| temp = f"""**Điểm đi:** {origin_office}\n**Điểm đến:** {destination_city}\n""" | |
| elif dest_office and departure_city: | |
| temp = f"""**Điểm đi:** {departure_city}\n**Điểm đến:** {dest_office}\n""" | |
| elif departure_city and destination_city: | |
| temp = f"""**Điểm đi:** {departure_city}\n**Điểm đến:** {destination_city}\n""" | |
| text[0] = temp + text[0] | |
| payload = { | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Tìm chuyến xe"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| async def route(request: Request): | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| origin_office = parameters.get("origin_office") | |
| dest_office = parameters.get("dest_office") | |
| raw_departure_city, raw_destination_city, raw_ticket_number , raw_date, _ = dialog_service.get_param_from_dialogflow(body) | |
| ticket_count = int(raw_ticket_number) if raw_ticket_number else 1 | |
| if raw_date is None: | |
| from_time, to_time = dialog_service.process_dates_to_timestamp() | |
| date = datetime.today().date().strftime('%m-%d-%Y') | |
| else: | |
| date = raw_date.strftime('%m-%d-%Y') | |
| from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date) | |
| origin_code, origin_id, origin_ids, dest_code, dest_id, dest_ids = None, None, None, None, None, None | |
| if origin_office: | |
| origin_id, origin_code = await dialog_service.find_id_and_code_provine_by_name_office(origin_office) | |
| origin_ids = await dialog_service.find_id_office_by_name_office(origin_office) | |
| elif raw_departure_city: | |
| origin_id, origin_code = get_origin_id_and_code(raw_departure_city) | |
| if dest_office: | |
| dest_id, dest_code = await dialog_service.find_id_and_code_provine_by_name_office(dest_office) | |
| dest_ids = await dialog_service.find_id_office_by_name_office(dest_office) | |
| elif raw_destination_city: | |
| dest_id, dest_code = get_origin_id_and_code(raw_destination_city) | |
| route_ids = await dialog_service.search_all_route_ids(origin_code=origin_code, from_id=origin_id, orign_ids=origin_ids, dest_code=dest_code, to_id=dest_id, dest_ids=dest_ids) | |
| payload = { | |
| "from_time": from_time, | |
| "to_time": to_time, | |
| "route_ids": route_ids, | |
| "ticket_count": 1, | |
| "sort_by": ["price", "departure_time"] | |
| } | |
| try: | |
| respone = await api.post("/search/trips", payload=payload) | |
| data = respone["data"]["items"] | |
| total = respone["data"]["total"] | |
| if total > 0: | |
| price = data[0]["price"] | |
| list_raw_departure_times = sorted(list(set([ trip["raw_departure_time"] for trip in data]))) | |
| list_raw_seat_type = list(set([ trip["seat_type_name"] for trip in data])) | |
| seat_type_trip_string = "**" + "** | **".join(map(str, list_raw_seat_type)) + "**" | |
| schedule_time_trip = "**" + "** | **".join(map(str, list_raw_departure_times)) + "**" | |
| duration = data[0]["duration"] | |
| link = f'https://stag.futabus.vn/dat-ve?from={departure_code}&fromTime={date}&isReturn=false&ticketCount={ticket_count}&to={destination_code}&toTime=' | |
| text = [f"Tuyến xe **{raw_departure_city}** - **{raw_destination_city}**\n \ | |
| Loại xe: {seat_type_trip_string} \n \ | |
| Thời gian hành trình: {duration} giờ \n \ | |
| Giá vé: **{price}** VND"] | |
| payload = { | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Tìm chuyến xe"}, | |
| {"text": "Xem lịch trình khác"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| text = [f"Hệ thống không tìm thấy tuyến xe **{raw_departure_city}** - **{raw_destination_city}**.\n Quý khách vui lòng thử lại với lộ trình khác hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."] | |
| payload = { | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Xem lịch trình khác"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| except Exception as e: | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def price(request: Request): | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| raw_departure_city, raw_destination_city, _, raw_date, _ = dialog_service.get_param_from_dialogflow(body) | |
| if raw_date is None: | |
| from_time, to_time = dialog_service.process_dates_to_timestamp() | |
| from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date) | |
| origin_office = parameters.get("origin_office") | |
| dest_office = parameters.get("dest_office") | |
| origin_code, origin_id, origin_ids, dest_code, dest_id, dest_ids = None, None, None, None, None, None | |
| if origin_office: | |
| origin_id, origin_code = await dialog_service.find_id_and_code_provine_by_name_office(origin_office) | |
| origin_ids = await dialog_service.find_id_office_by_name_office(origin_office) | |
| elif raw_departure_city: | |
| origin_id, origin_code = get_origin_id_and_code(raw_departure_city) | |
| if dest_office: | |
| dest_id, dest_code = await dialog_service.find_id_and_code_provine_by_name_office(dest_office) | |
| dest_ids = await dialog_service.find_id_office_by_name_office(dest_office) | |
| elif raw_destination_city: | |
| dest_id, dest_code = get_origin_id_and_code(raw_destination_city) | |
| route_ids = await dialog_service.search_all_route_ids(origin_code=origin_code, from_id=origin_id, orign_ids=origin_ids, dest_code=dest_code, to_id=dest_id, dest_ids=dest_ids) | |
| payload = { | |
| "from_time": from_time, | |
| "to_time": to_time, | |
| "route_ids": route_ids, | |
| "ticket_count": 1, | |
| "sort_by": ["price", "departure_time"] | |
| } | |
| try: | |
| respone = await api.post("/search/trips", payload=payload) | |
| total = respone["data"]["total"] | |
| if total > 0: | |
| price = respone["data"]["items"][0]["price"] | |
| text = [f"Tuyến xe **{raw_departure_city}** - **{raw_destination_city}**\n" | |
| f"Giá vé: **{price}** VND.\n \ | |
| Bạn có muốn đặt vé không?" | |
| ] | |
| payload = { | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Có, tôi muốn đặt vé"}, | |
| {"text": "Xem giá vé tuyến xe khác"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| text = [f"Hệ thống không tìm thấy tuyến xe **{raw_departure_city}** - **{raw_destination_city}**.\n Quý khách vui lòng thử lại với lộ trình khác hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Xem giá vé lịch trình khác"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| except: | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def get_trip_list(request: Request) -> Response: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| raw_departure_city, raw_destination_city, raw_ticket_number, raw_date, _ = dialog_service.get_param_from_dialogflow(body) | |
| origin_office = parameters.get("origin_office") | |
| dest_office = parameters.get("dest_office") | |
| time = parameters.get("time-select") | |
| time = extra_time_dialogflow(time) | |
| if isinstance(time, list): | |
| parameters = { | |
| "is_time_ambiguous": True | |
| } | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date) | |
| ticket_count = int(raw_ticket_number) if raw_ticket_number else 1 | |
| origin_code, origin_id, origin_ids, dest_code, dest_id, dest_ids = None, None, None, None, None, None | |
| if origin_office: | |
| origin_id, origin_code = await dialog_service.find_id_and_code_provine_by_name_office(origin_office) | |
| origin_ids = await dialog_service.find_id_office_by_name_office(origin_office) | |
| elif raw_departure_city: | |
| origin_id, origin_code = get_origin_id_and_code(raw_departure_city) | |
| if dest_office: | |
| dest_id, dest_code = await dialog_service.find_id_and_code_provine_by_name_office(dest_office) | |
| dest_ids = await dialog_service.find_id_office_by_name_office(dest_office) | |
| elif raw_destination_city: | |
| dest_id, dest_code = get_origin_id_and_code(raw_destination_city) | |
| route_ids = await dialog_service.search_all_route_ids(origin_code=origin_code, from_id=origin_id, orign_ids=origin_ids, dest_code=dest_code, to_id=dest_id, dest_ids=dest_ids) | |
| try: | |
| data = await dialog_service.search_trip(from_time, to_time, route_ids, ticket_count) | |
| if len(data) > 0: | |
| ################################## bug choox nay | |
| if origin_office: | |
| origin_id = origin_ids | |
| if dest_office: | |
| dest_id = dest_ids | |
| trip_by_time_office = dialog_service.get_trip_by_time_and_office_id(data, time, origin_id, dest_id) | |
| # Nếu có chuyến xe theo thời gian và văn phòng chỉ định | |
| if trip_by_time_office: | |
| print(trip_by_time_office) | |
| parameters = { | |
| "is_valid_trip": True, | |
| "trip": trip_by_time_office | |
| } | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| # Danh sách chuyến xe khớp với văn phòng đón hoặc văn phòng trả | |
| if origin_office and dest_office: | |
| data_by_office = dialog_service.get_all_trip_by_office(data, origin_id, dest_id) | |
| elif origin_office: | |
| data_by_office = dialog_service.get_all_trip_by_office(data,origin_id=origin_id) | |
| elif dest_office: | |
| data_by_office = dialog_service.get_all_trip_by_office(data, dest_id=dest_id) | |
| else: | |
| data_by_office = data | |
| # Tìm 4 chuyến xe gần thời gian chỉ định nhất | |
| trip_surrounding_time = dialog_service.get_4_surrounding_trip(data_by_office, time) | |
| trip_dialogflow = [] | |
| for trip in trip_surrounding_time: | |
| if ticket_count <= trip["empty_seat_quantity"]: | |
| trip_dialogflow.append({"trip_id": trip["id"], "route":f'{trip["raw_departure_time"]} | {trip["route"]["origin_hub_name"]} => {trip["route"]["dest_hub_name"]}'}) | |
| text = ["Quý khách vui lòng lựa chọn chuyến xe\n" + "\n".join(f'{i+1}. {trip["route"]}' for i, trip in enumerate(trip_dialogflow))] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": trip["route"]} for trip in (trip_dialogflow) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| parameters = { | |
| "trip_select": trip_dialogflow, | |
| "trips": trip_surrounding_time, | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload,parameters=parameters) | |
| text = [f"Hệ thống không tìm thấy tuyến xe **{raw_departure_city}** - **{raw_destination_city}**.\n Quý khách vui lòng thử lại với lộ trình khác hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Xem tuyến xe khác"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| except Exception as e: | |
| print(e) | |
| return JSONResponse( | |
| { | |
| "fulfillment_response": { | |
| "messages": [ | |
| { | |
| "text": { | |
| "text": ["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."] | |
| } | |
| } | |
| ] | |
| }, | |
| } | |
| ) | |
| async def booking_trip(request: Request) -> Response: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| raw_departure_city, raw_destination_city, raw_ticket_number, raw_date, raw_time_of_day = dialog_service.get_param_from_dialogflow(body) | |
| origin_office = parameters.get("origin_office") | |
| dest_office = parameters.get("dest_office") | |
| from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date) | |
| ticket_count = int(raw_ticket_number) if raw_ticket_number else 1 | |
| origin_code, origin_id, origin_ids, dest_code, dest_id, dest_ids = None, None, None, None, None, None | |
| if origin_office: | |
| origin_id, origin_code = await dialog_service.find_id_and_code_provine_by_name_office(origin_office) | |
| origin_ids = await dialog_service.find_id_office_by_name_office(origin_office) | |
| elif raw_departure_city: | |
| origin_id, origin_code = get_origin_id_and_code(raw_departure_city) | |
| if dest_office: | |
| dest_id, dest_code = await dialog_service.find_id_and_code_provine_by_name_office(dest_office) | |
| dest_ids = await dialog_service.find_id_office_by_name_office(dest_office) | |
| elif raw_destination_city: | |
| dest_id, dest_code = get_origin_id_and_code(raw_destination_city) | |
| route_ids = await dialog_service.search_all_route_ids(origin_code=origin_code, from_id=origin_id, orign_ids=origin_ids, dest_code=dest_code, to_id=dest_id, dest_ids=dest_ids) | |
| try: | |
| data = await dialog_service.search_trip(from_time, to_time, route_ids, ticket_count) | |
| if len(data) > 0: | |
| trips = [] | |
| routes_name = [] | |
| for trip in data: | |
| if ticket_count <= trip["empty_seat_quantity"]: | |
| route = f"{trip['route']['origin_hub_name']} => {trip['route']['dest_hub_name']}" | |
| if trip["route"] and route not in routes_name: | |
| routes_name.append(f"{trip['route']['origin_hub_name']} => {trip['route']['dest_hub_name']}") | |
| trips.append({ | |
| "route_name": f"{trip['route']['origin_hub_name']} => {trip['route']['dest_hub_name']}", | |
| "route_id": trip["route_id"], | |
| "id": trip["id"], | |
| "departure_date": trip["raw_departure_date"], | |
| "departure_time": trip["raw_departure_time"], | |
| "kind": trip["seat_type_name"], | |
| "way_id": trip["way_id"] | |
| }) | |
| text = ["Quý khách vui lòng lựa chọn chuyến xe\n" + "\n".join(f"{i+1}. {name}" for i, name in enumerate(routes_name))] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": name} for name in (routes_name) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| parameters = { | |
| "trip_list": trips, | |
| "routes_name": routes_name | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload,parameters=parameters) | |
| text = [f"Hệ thống không tìm thấy tuyến xe **{raw_departure_city}** - **{raw_destination_city}**.\n Quý khách vui lòng thử lại với lộ trình khác hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Xem tuyến xe khác"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| except Exception as e: | |
| print(e) | |
| return JSONResponse( | |
| { | |
| "fulfillment_response": { | |
| "messages": [ | |
| { | |
| "text": { | |
| "text": ["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."] | |
| } | |
| } | |
| ] | |
| }, | |
| } | |
| ) | |
| async def is_valid_select_trip(request: Request) -> Response: | |
| body = await request.json() | |
| raw_input = body.get("text", "") | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip_select: list[dict[str, any]] = parameters.get("trip_select") | |
| trips: list[dict[str, any]] = parameters.get("trips") | |
| if trip_select is None and trips is None: | |
| return DialogFlowResponseAPI() | |
| if raw_input: | |
| raw_input = raw_input.strip() | |
| for item in trip_select: | |
| if item["route"] == raw_input: | |
| id = int(item["trip_id"]) | |
| trip = dialog_service.get_trip_by_id(id, trips) | |
| parameters = { | |
| "is_valid_trip": True, | |
| "trip": trip | |
| } | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| parameters = { | |
| "is_valid_trip": False, | |
| } | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| async def check_time_ambiguous(request: Request) -> Response: | |
| try: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| time = parameters.get("time-select") | |
| parameters = {} | |
| time = extra_time_dialogflow(time) | |
| if isinstance(time, list) or time is None: | |
| parameters["is_time_ambiguous"] = True | |
| else: | |
| parameters["is_time_ambiguous"] = None | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| except Exception as e: | |
| print(e) | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def select_time(request: Request) -> Response: | |
| try: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| time = parameters.get("time-select") | |
| parameters = {} | |
| time = extra_time_dialogflow(time) | |
| text = [] | |
| if time is None: | |
| text = ["Quý khách vui lòng chỉ định thời gian đi cụ thể trong ngày?"] | |
| elif isinstance(time, list): | |
| text = [f"Quý khách dự định đi vào lúc"] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": item} for item in (time) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| else: | |
| parameters["is_time_ambiguous"] = None | |
| return DialogFlowResponseAPI(text=text,payload=payload,parameters=parameters) | |
| except Exception as e: | |
| print(e) | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def time_trip(request: Request) -> Response: | |
| try: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip_list: list[Dict[str, any]] = parameters.get("trip_list", []) | |
| raw_route_id = parameters.get("route_id") | |
| route_name = parameters.get("route_name", "") | |
| raw_time = parameters.get("time-select") | |
| time_list = parameters.get("time_list", []) | |
| is_has_time = parameters.get("is_has_time", False) | |
| route_id = int(raw_route_id) if raw_route_id else None | |
| text = [] | |
| quick_time_reply = [] | |
| parameters = {} | |
| if raw_time: | |
| time = extra_time_dialogflow(raw_time) | |
| quick_time_reply = time_list | |
| if isinstance(time, list): | |
| parameters["time_select"] = None | |
| parameters["is_time_ambiguous"] = True | |
| text = [f"Quý khách dự định đi vào lúc"] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": item} for item in (time) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload ,parameters=parameters) | |
| else: | |
| if is_has_time: | |
| text = [f"Quý khách lựa chọn thời gian chuyến {route_name}\n" + " | ".join([item["time"] for item in quick_time_reply])] | |
| parameters["is_has_time"] = None | |
| else: | |
| parameters["is_has_time"] = True | |
| return DialogFlowResponseAPI(text=text,parameters=parameters) | |
| else: | |
| for trip in trip_list: | |
| if (trip["route_id"]) == route_id: | |
| time_list.append({"time": trip["departure_time"], "trip_id": trip["id"]}) | |
| quick_time_reply = time_list | |
| text = [f"Quý khách lựa chọn thời gian chuyến {route_name}\n" + " | ".join([item["time"] for item in quick_time_reply])] | |
| parameters["time_list"] = time_list | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": time["time"]} for time in (quick_time_reply) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload ,parameters=parameters) | |
| except Exception as e: | |
| print(e) | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def is_valid_select_time(request: Request) -> Response: | |
| try: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip_list: list[Dict[str, any]] = parameters.get("trip_list", []) | |
| raw_route_id = parameters.get("route_id") | |
| raw_departure_city, raw_destination_city, raw_ticket_number, raw_date, raw_time_of_day = dialog_service.get_param_from_dialogflow(body) | |
| route_id = int(raw_route_id) if raw_route_id else None | |
| from_time, to_time = dialog_service.process_dates_to_timestamp(raw_date) | |
| ticket_count = int(raw_ticket_number) if raw_ticket_number else 1 | |
| origin_office = parameters.get("origin_office") | |
| dest_office = parameters.get("dest_office") | |
| origin_code, origin_id, origin_ids, dest_code, dest_id, dest_ids = None, None, None, None, None, None | |
| if origin_office: | |
| origin_id, origin_code = await dialog_service.find_id_and_code_provine_by_name_office(origin_office) | |
| origin_ids = await dialog_service.find_id_office_by_name_office(origin_office) | |
| elif raw_departure_city: | |
| origin_id, origin_code = get_origin_id_and_code(raw_departure_city) | |
| if dest_office: | |
| dest_id, dest_code = await dialog_service.find_id_and_code_provine_by_name_office(dest_office) | |
| dest_ids = await dialog_service.find_id_office_by_name_office(dest_office) | |
| elif raw_destination_city: | |
| dest_id, dest_code = get_origin_id_and_code(raw_destination_city) | |
| route_ids = await dialog_service.search_all_route_ids(origin_code=origin_code, from_id=origin_id, orign_ids=origin_ids, dest_code=dest_code, to_id=dest_id, dest_ids=dest_ids) | |
| time_list: list[Dict[str, any]] = parameters.get("time_list", []) | |
| time_select = parameters.get("time-select") | |
| route_name = parameters.get("route_name") | |
| is_has_time = parameters.get("is_has_time") | |
| if len(time_list) == 0: | |
| for trip in trip_list: | |
| if (trip["route_id"]) == route_id: | |
| time_list.append({"time": trip["departure_time"], "trip_id": trip["id"]}) | |
| if time_select: | |
| time_select = extra_time_dialogflow(time_select) | |
| for time in time_list: | |
| if time_select == time["time"]: | |
| id = int(time["trip_id"]) | |
| trip = await dialog_service.search_trip_by_id(id, from_time, to_time, route_ids, ticket_count) | |
| departure_date = trip["raw_departure_date"] | |
| parameters = { | |
| "is_valid_time": True, | |
| "departure_time": time_select, | |
| "departure_date": departure_date, | |
| "trip": trip, | |
| } | |
| text = [f'Quý khách chọn chuyến **{time_select}** | **{route_name}**'] | |
| return DialogFlowResponseAPI(text=text, parameters=parameters) | |
| if is_has_time: | |
| time_list = find_surrounding_times(time_list, time_select) | |
| parameters = { | |
| "time_list": time_list, | |
| "is_valid_time": False | |
| } | |
| return DialogFlowResponseAPI(parameters=parameters) | |
| parameters = { | |
| "time_select": None, | |
| "is_valid_time": False | |
| } | |
| text = [] | |
| return DialogFlowResponseAPI(text=text, parameters=parameters) | |
| except Exception as e: | |
| print(e) | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def seats_trip(request: Request) -> Response: | |
| try: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip = parameters.get("trip", None) | |
| route_id = int(trip.get("route_id")) if trip.get("route_id") else None | |
| trip_id = int(trip.get("id")) if trip.get("id") else None | |
| departure_date: str = trip.get("raw_departure_date") | |
| departure_time: str = trip.get("raw_departure_time") | |
| kind: str = trip.get("seat_type_name") | |
| seats = await dialog_service.seats_trip(route_id, trip_id, departure_date, departure_time, kind) | |
| seats_empty = [ seat for seat in seats if seat["bookStatus"] == 0 ] | |
| seats_empty.sort(key=lambda x: x["chair"]) | |
| text=["Vui lòng chọn ghế"] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": seat["chair"]} for seat in (seats_empty) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| parameters = { | |
| "seat_list": seats | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload, parameters=parameters) | |
| except Exception as e: | |
| print(e) | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def is_valid_select_seat(request: Request) -> Response: | |
| try: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip: list[dict[str, any]] = parameters.get("trip", None) | |
| route_id = int(trip.get("route_id")) if trip.get("route_id") else None | |
| trip_id = int(trip.get("id")) if trip.get("id") else None | |
| departure_date: str = trip.get("raw_departure_date") | |
| departure_time: str = trip.get("raw_departure_time") | |
| kind: str = trip.get("seat_type_name") | |
| seat: str = parameters.get("seat") | |
| is_valid = await dialog_service.is_valid_select_seat(seat, route_id, trip_id, departure_date, departure_time, kind) | |
| if is_valid: | |
| parameters = { | |
| "is_valid_seat": True, | |
| "seat": seat | |
| } | |
| text = [f"Quý khách chọn ghế **{seat}**"] | |
| else: | |
| parameters = { | |
| "is_valid_seat": False, | |
| "seat": None | |
| } | |
| text = [f"Ghế **{seat}** không hợp lệ. Quý khách vui lòng chọn ghế khác"] | |
| return DialogFlowResponseAPI(text=text, parameters=parameters) | |
| except Exception as e: | |
| return DialogFlowResponseAPI(text=["Hệ thống xảy ra lỗi. Quý khách vui lòng thử lại sau hoặc liên hệ Trung tâm tổng đài 1900 6067 để được hỗ trợ."]) | |
| async def pickup(request: Request) -> Response: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip: list[dict[str, any]] = parameters.get("trip", {}) | |
| route_id = int(trip.get("route_id")) if trip.get("route_id") else None | |
| way_id = int(trip.get("way_id")) if trip.get("way_id") else None | |
| pickup_list = await dialog_service.pickup_list(route_id, way_id) | |
| text=["Quý khách vui lòng chọn điểm đón"] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": pickup["name"]} for pickup in (pickup_list) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| parameters = { | |
| "pickup_list": pickup_list | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload, parameters=parameters) | |
| async def is_valid_select_pickup(request: Request) -> Response: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip: list[dict[str, any]] = parameters.get("trip", {}) | |
| route_id = int(trip.get("route_id")) if trip.get("route_id") else None | |
| way_id = int(trip.get("way_id")) if trip.get("way_id") else None | |
| raw_input = (body.get("text","")) | |
| pickup = raw_input.strip() | |
| is_valid = await dialog_service.is_valid_pickup(pickup, route_id, way_id) | |
| if is_valid: | |
| parameters = { | |
| "is_valid_pickup": True, | |
| "pick_up": pickup | |
| } | |
| text = [f"Quý khách chọn điểm đón **{pickup}**"] | |
| else: | |
| parameters = { | |
| "is_valid_pickup": False, | |
| } | |
| text = [f"Điểm đón không hợp lệ. Quý khách vui lòng chọn điểm đón khác"] | |
| return DialogFlowResponseAPI(text=text, parameters=parameters) | |
| async def dropoff(request: Request) -> Response: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip: list[dict[str, any]] = parameters.get("trip", {}) | |
| route_id = int(trip.get("route_id")) if trip.get("route_id") else None | |
| way_id = int(trip.get("way_id")) if trip.get("way_id") else None | |
| dropoff_list = await dialog_service.dropoff_list(route_id, way_id) | |
| text=["Quý khách vui lòng chọn điểm trả khách"] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": dropoff["name"]} for dropoff in (dropoff_list) | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| parameters = { | |
| "dropoff_list": dropoff_list | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload, parameters=parameters) | |
| async def is_valid_select_dropoff(request: Request) -> Response: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| trip: list[dict[str, any]] = parameters.get("trip", {}) | |
| route_id = int(trip.get("route_id")) if trip.get("route_id") else None | |
| way_id = int(trip.get("way_id")) if trip.get("way_id") else None | |
| raw_input = (body.get("text","")) | |
| dropoff = raw_input.strip() | |
| is_valid = await dialog_service.is_valid_dropoff(dropoff, route_id, way_id) | |
| if is_valid: | |
| parameters = { | |
| "is_valid_dropoff": True, | |
| "drop_off": dropoff | |
| } | |
| text = [f"Quý khách chọn điểm trả khách **{dropoff}**"] | |
| else: | |
| parameters = { | |
| "is_valid_dropoff": False, | |
| } | |
| text = [f"Điểm trả khách không hợp lệ. Quý khách vui lòng chọn điểm trả khách khác"] | |
| return DialogFlowResponseAPI(text=text, parameters=parameters) | |
| async def response_ticket_info(request: Request) -> Response: | |
| body = await request.json() | |
| session_info = body.get("sessionInfo", {}) | |
| parameters = session_info.get("parameters") | |
| user_name = parameters.get("user_name") | |
| phone_number = parameters.get("phone_number") | |
| email = parameters.get("email") | |
| seat = parameters.get("seat") | |
| pickup = parameters.get("pick_up") | |
| dropoff = parameters.get("drop_off") | |
| trip = parameters.get("trip", {}) | |
| route_name = trip["route"]["name"] | |
| time = trip["raw_departure_time"] | |
| date = trip["raw_departure_date"] | |
| price = int(trip.get("price")) if trip.get("price") else None | |
| text = [ | |
| f" \ | |
| **Thông tin hành khách**\n\ | |
| **Họ và tên** {user_name} \n\ | |
| **Số điện thoại** {phone_number}\n\ | |
| **Email** {email} \n\ | |
| **Thông tin lượt đi**\n\ | |
| **Tuyến xe** {route_name} \n\ | |
| **Thời gian xuất bến** {time} {date} \n\ | |
| **Số ghế** {seat} \n\ | |
| **Điểm lên xe** {pickup} \n\ | |
| **Điểm trả khách** {dropoff} \n\ | |
| **Tổng tiền lượt đi** {price} VND \ | |
| " | |
| ] | |
| payload={ | |
| "richContent": [ | |
| [ | |
| { | |
| "type": "chips", | |
| "options": [ | |
| {"text": "Đặt vé"}, | |
| {"text": "Không, cảm ơn"} | |
| ] | |
| } | |
| ] | |
| ] | |
| } | |
| return DialogFlowResponseAPI(text=text, payload=payload) | |
| def home(): | |
| return "Hello World!" | |
| async def index(request: Request): | |
| return templates.TemplateResponse("index.html", {"request": request, "title": "Dawi Chatbot"}) |