Spaces:
Running
Running
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.services import api | |
from app.utils.constants import code_province | |
from app.types.Respone import DialogFlowResponseAPI | |
router = APIRouter() | |
templates = Jinja2Templates(directory="app/templates") | |
def to_datetime_from_Dialogflow(time: dict): | |
date_time = datetime(int(time["year"]), int(time["month"]), int(time["day"])) | |
return date_time | |
# Xử lý fromTime và toTime | |
def process_dates_to_timestamp(from_time: datetime = None, to_time: datetime = None): | |
print(from_time) | |
if to_time is None and from_time is not None: | |
to_time = from_time.replace(hour=23, minute=59, second=59) | |
if from_time is None: | |
today = datetime.today().date() | |
from_time = datetime.combine(today, datetime.min.time()) | |
to_time = datetime.combine(today, datetime.max.time()) - timedelta(microseconds=1) | |
return int(from_time.timestamp()) * 1000 , int(to_time.timestamp()) * 1000 | |
def get_param_from_dialogflow(body: any): | |
session_info = body.get("sessionInfo", {}) | |
parameters = session_info.get("parameters") | |
raw_date = parameters.get("date") | |
if raw_date is not None: | |
raw_date = to_datetime_from_Dialogflow(raw_date) | |
raw_departure_city = parameters.get("departure_city") | |
raw_destination_city = parameters.get("destination_city") | |
raw_ticket_number = parameters.get("ticket_number") | |
raw_time_of_day = parameters.get("time_of_day") | |
return raw_departure_city, raw_destination_city, raw_ticket_number, raw_date, raw_time_of_day | |
async def search_route_ids_from_province(departure_code: str, destination_code: str): | |
response = await api.get(f'/metadata/office/routes?DestCode={destination_code}&OriginCode={departure_code}') | |
route_ids = [] | |
if isinstance(response, list): # Kiểm tra nếu data là danh sách | |
route_ids = [route.get("routeId", -1) for route in response] | |
return route_ids | |
async def route(request: Request): | |
body = await request.json() | |
raw_departure_city, raw_destination_city, raw_ticket_number , raw_date, _ = 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 = process_dates_to_timestamp() | |
date = datetime.today().date().strftime('%m-%d-%Y') | |
else: | |
date = raw_date.strftime('%m-%d-%Y') | |
from_time, to_time = process_dates_to_timestamp(raw_date) | |
departure_code = code_province.get(raw_departure_city) | |
destination_code = code_province.get(raw_destination_city) | |
route_dep_to_des = await search_route_ids_from_province(departure_code,destination_code) | |
route_des_to_dep = await search_route_ids_from_province(destination_code,departure_code) | |
routes_ids = list(set(route_dep_to_des + route_des_to_dep)) | |
payload = { | |
"from_time": from_time, | |
"to_time": to_time, | |
"route_ids": routes_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]))) | |
schedule_time_trip = "**" + "** | **".join(map(str, list_raw_departure_times)) + "**" | |
link = f'https://stag.futabus.vn/dat-ve?from={departure_code}&fromTime={date}&isReturn=false&ticketCount={ticket_count}&to={destination_code}&toTime=' | |
text = [f"Lộ trình **{raw_departure_city}** - **{raw_destination_city}**: **{total}** tuyến xe.\n \ | |
Thời gian các tuyến xe khởi hành: {schedule_time_trip}\n \ | |
Giá vé: **{price}** VND.\n \ | |
Quý khách vui lòng truy cập vào [**tại đây**]({link}) để xem chi tiết lịch trình."] | |
payload = { | |
"richContent": [ | |
[ | |
{ | |
"type": "chips", | |
"options": [ | |
{"text": "Đặt vé"}, | |
{"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 nào phù hợp với lộ trình **{raw_departure_city}** - **{raw_destination_city}** của quý khách.\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) | |
# return DialogFlowResponeAPI(text=['Hello']) | |
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() | |
raw_departure_city, raw_destination_city, _, raw_date, _ = get_param_from_dialogflow(body) | |
if raw_date is None: | |
from_time, to_time = process_dates_to_timestamp() | |
from_time, to_time = process_dates_to_timestamp(raw_date) | |
departure_code = code_province.get(raw_departure_city) | |
destination_code = code_province.get(raw_destination_city) | |
route_dep_to_des = await search_route_ids_from_province(departure_code,destination_code) | |
route_des_to_dep = await search_route_ids_from_province(destination_code,departure_code) | |
routes_ids = list(set(route_dep_to_des + route_des_to_dep)) | |
payload = { | |
"from_time": from_time, | |
"to_time": to_time, | |
"route_ids": routes_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"Lộ trình **{raw_departure_city}** - **{raw_destination_city}**\n" | |
f"Giá vé: **{price}** VND.\nBạ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é 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 nào phù hợp với lộ trình **{raw_departure_city}** - **{raw_destination_city}** của quý khách.\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 booking_trip(request: Request) -> Response: | |
body = await request.json() | |
raw_departure_city, raw_destination_city, raw_ticket_number, raw_date, raw_time_of_day = get_param_from_dialogflow(body) | |
date = raw_date.strftime('%m-%d-%Y') | |
from_time, to_time = process_dates_to_timestamp(raw_date) | |
ticket_count = int(raw_ticket_number) if raw_ticket_number else 1 | |
departure_code = code_province.get(raw_departure_city) | |
destination_code = code_province.get(raw_destination_city) | |
route_dep_to_des = await search_route_ids_from_province(departure_code,destination_code) | |
route_des_to_dep = await search_route_ids_from_province(destination_code,departure_code) | |
routes_ids = list(set(route_dep_to_des + route_des_to_dep)) | |
payload = { | |
"from_time": from_time, | |
"to_time": to_time, | |
"route_ids": routes_ids, | |
"ticket_count": ticket_count, | |
"sort_by": ["price", "departure_time"] | |
} | |
try: | |
respone = await api.post("/search/trips", payload=payload) | |
if respone.get('status') == 200: | |
data = respone["data"]["items"] | |
total = respone["data"]["total"] | |
if total > 0: | |
price = respone["data"]["items"][0]["price"] | |
list_raw_departure_times = sorted(list(set([ trip["raw_departure_time"] for trip in data]))) | |
schedule_time_trip = "**" + "** | **".join(map(str, list_raw_departure_times)) + "**" | |
link = f'https://stag.futabus.vn/dat-ve?from={departure_code}&fromTime={date}&isReturn=false&ticketCount={ticket_count}&to={destination_code}&toTime=' | |
text= [f"Lộ trình **{raw_departure_city}** - **{raw_destination_city}**: **{total}** tuyến xe.\n" | |
f"Thời gian các tuyến xe khởi hành: {schedule_time_trip}\n" | |
f"Giá vé: **{price}** VND.\n" | |
f"Quý khách vui lòng truy cập vào [**tại đây**]({link}) để tiến hành đặt vé."] | |
return DialogFlowResponseAPI(text=text) | |
text = [f"Hệ thống không tìm thấy tuyến xe nào phù hợp với lộ trình **{raw_departure_city}** - **{raw_destination_city}** của quý khách.\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: | |
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ợ."] | |
} | |
} | |
] | |
}, | |
} | |
) | |
def home(): | |
return "Hello World!" | |
async def index(request: Request): | |
return templates.TemplateResponse("index.html", {"request": request, "title": "Dawi Chatbot"}) |