Esempio n. 1
0
def confirm_parking(bot, update):
    chat_id = str(update.callback_query.message.chat_id)
    data = separate_callback_data(update.callback_query.data)

    location = data[1]

    keyboard = [
        [InlineKeyboardButton("📍 Mostra sulla mappa", callback_data=ccd("SEND_LOCATION", location))],
        [InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))]
    ]

    day_group = get_trip("Discesa", common.today(), chat_id)
    day_group["Location"] = location

    bot.edit_message_text(chat_id=chat_id,
                          message_id=update.callback_query.message.message_id,
                          text=f"Posizione impostata con successo: {location}",
                          reply_markup=InlineKeyboardMarkup(keyboard))

    for passenger_group in day_group["Temporary"], day_group["Permanent"]:
        for passenger in passenger_group:
            bot.send_message(chat_id=passenger,
                             text=f"Per il viaggio di ritorno,"
                             f" [{get_name(chat_id)}](tg://user?id={chat_id})"
                             f" ha impostato il luogo di ritrovo:\n📍 {location}.",
                             reply_markup=InlineKeyboardMarkup(keyboard))
Esempio n. 2
0
def trips_keyboard(chat_id):
    keyboard = [[InlineKeyboardButton("Aggiungi un nuovo viaggio", callback_data=ccd("TRIPS", "ADD"))]]
    today_number = datetime.datetime.today().weekday()

    for item in range(len(common.days)):
        day = common.day_to_string((item + today_number) % len(common.days))

        if day == "Sabato" or day == "Domenica":  # Sabato, domenica
            continue

        for direction in "Salita", "Discesa":
            try:
                group = get_trip(direction, day, chat_id)

                if group["Suspended"]:
                    counter = "SOSP."
                else:
                    counter = f"{len(group['Permanent']) + len(group['Temporary'])}"

                if common.is_sessione():
                    shown_day = f"{day} {datetime.datetime.today().day + item}"
                else:
                    shown_day = day

                keyboard.append(
                    [InlineKeyboardButton(f"{shown_day}: {group['Time']}"
                                          f" {common.dir_name(direction)} ({counter})",
                                          callback_data=ccd("TRIPS", "EDIT_TRIP", direction, day))])
            except Exception:  # Viaggio non segnato...
                continue

    keyboard.append([InlineKeyboardButton("↩ Indietro", callback_data=ccd("ME_MENU"))])
    keyboard.append([InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))])

    return InlineKeyboardMarkup(keyboard)
Esempio n. 3
0
def fetch_sessione():
    text = ["Riepilogo viaggi:"]
    today_number = datetime.datetime.today().weekday()

    for item in range(len(common.days)):
        day = common.day_to_string((item + today_number) % len(common.days))

        if day == "Sabato" or day == "Domenica":  # Sabato, domenica
            continue

        empty_day = True
        for direction in "Salita", "Discesa":
            bookings = get_all_trips_fixed_direction(direction, day)

            if len(bookings) > 0:
                if empty_day:
                    text.append(
                        f"\n\n🗓 Viaggi di {day.lower()} {datetime.datetime.today().day + item}"
                    )

                empty_day = False
                for time, driver in bookings:
                    trip = get_trip(direction, day, driver)
                    # Raccolgo in una list comprehension le persone che partecipano al viaggio
                    people = [
                        f"[{get_name(user)}](tg://user?id={user})"
                        for user in trip["Temporary"]
                    ]

                    # Aggiungo ogni viaggio trovato alla lista
                    text.append(
                        f"\n🚗 [{get_name(driver)}](tg://user?id={driver}) "
                        f"(*{time}*, {common.dir_name(direction)}): {', '.join(people)}\n"
                    )

        if empty_day:
            text.append(
                f"\n😱 Nessuno viaggio previsto per {day.lower()} {datetime.datetime.today().day + item}."
            )

    keyboard = [[
        InlineKeyboardButton("🔂 Prenota",
                             callback_data=ccd("BOOKING", "START",
                                               "Temporary"))
    ], [InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))]]

    return "".join(text), InlineKeyboardMarkup(keyboard)
Esempio n. 4
0
def alert_user(bot, update):
    chat_id = str(update.callback_query.message.chat_id)
    data = separate_callback_data(update.callback_query.data)
    action = data[1]

    if action == "CO_BO":
        direction, day, user, mode = data[2:]  # Utente della prenotazione

        trip = get_trip(direction, day, chat_id)
        occupied_slots = len(trip["Permanent"]) + len(trip["Temporary"])
        total_slots = get_slots(chat_id)

        if occupied_slots < total_slots:
            if user not in trip[mode]:
                add_passenger(direction, day, chat_id, mode, user)
                edited_text = "Hai una nuova prenotazione: " \
                    f"\n\n👤: [{get_name(user)}](tg://user?id={user}) ✔" \
                    f"(*{total_slots - occupied_slots - 1} posti rimanenti*)" \
                    f"\n🗓 {day}" \
                    f"\n🕓 {get_time(direction, day, chat_id)}" \
                    f"\n{common.dir_name(direction)}" \
                    f"\n{common.mode_name(mode)}" \
                    f".\n\nPrenotazione confermata con successo."
                booker_text = f"[{get_name(chat_id)}](tg://user?id={chat_id})" \
                    f" ha confermato la tua prenotazione."
            else:
                edited_text = "⚠ Attenzione, questa persona è già prenotata con te in questo viaggio."
                booker_text = "⚠ Ti sei già prenotato in questa data con questa persona!"
        else:
            edited_text = "⚠ Attenzione, hai esaurito i posti disponibili per questo viaggio. Non è" \
                          " possibile confermarlo."
            booker_text = f"⚠ Mi dispiace, ma qualcun'altro si è prenotato prima di te. Contatta " \
                f"[{get_name(chat_id)}](tg://user?id={chat_id}) per disponibilità posti."

        bot.send_message(chat_id=user, parse_mode="Markdown", text=booker_text)

        bot.edit_message_text(
            chat_id=chat_id,
            message_id=update.callback_query.message.message_id,
            parse_mode="Markdown",
            reply_markup=None,
            text=edited_text)
Esempio n. 5
0
def inline_handler(bot, update):
    query = update.inline_query.query.lower()
    chat_id = str(update.inline_query.from_user.id)
    if not query or chat_id not in all_users():
        return

    results = []

    for day in common.work_days:
        for direction in "Salita", "Discesa":
            for driver in get_trip_group(direction, day):
                driver_name = get_name(driver)
                if query in day.lower() or query in driver_name.lower():
                    # Visualizzo solo le query contenenti giorno o autista
                    trip = get_trip(direction, day, driver)
                    people = ', '.join([f"{get_name(user)}" for mode in trip
                                        if mode == "Temporary" or mode == "Permanent" for user in trip[mode]])
                    results.append(
                        InlineQueryResultArticle(
                            id=f"{direction}{day}{driver}",
                            title=f"{driver_name.split(' ')[-1]} {day} {common.dir_name(direction)}",
                            input_message_content=InputTextMessageContent(
                                f"\n\n🚗 {driver_name}"
                                f"{' - 🚫 Sospeso' if trip['Suspended'] else ''}"
                                f"\n🗓 {day}"
                                f"\n🕓 {trip['Time']}"
                                f"\n{common.dir_name(direction)}"
                                f"\n👥 {people}"
                            ),
                            hide_url=True,
                            thumb_url=common.povo_url if direction == "Salita" else common.nest_url,
                            thumb_height=40,
                            thumb_width=40
                        )
                    )

    bot.answer_inline_query(update.inline_query.id, results)
Esempio n. 6
0
def fetch_bookings(chat_id, day):
    if common.is_weekday(day):
        text = [f"Lista dei viaggi di {day.lower()}:"]

        for direction in "Salita", "Discesa":
            text.append(f"\n\n{common.dir_name(direction)}\n")

            bookings = get_all_trips_fixed_direction(direction, day)

            if len(bookings) > 0:
                for time, driver in bookings:
                    trip = get_trip(direction, day, driver)
                    # Raccolgo in una list comprehension le persone che partecipano al viaggio
                    people = [
                        f"[{get_name(user)}](tg://user?id={user})"
                        for mode in trip
                        if mode == "Temporary" or mode == "Permanent"
                        for user in trip[mode]
                    ]

                    # Aggiungo ogni viaggio trovato alla lista
                    text.append(
                        f"\n🚗 [{get_name(driver)}](tg://user?id={driver})"
                        f" - 🕓 *{time}*:"
                        f"\n👥 {', '.join(people)}\n")
            else:
                text.append("\n🚶🏻‍♂ Nessuna persona in viaggio oggi.")

        if is_registered(chat_id):
            day_subkeyboard = []

            for wkday in common.work_days:
                ccd_text = "☑" if wkday == day else wkday[:2]
                day_subkeyboard.append(
                    InlineKeyboardButton(ccd_text,
                                         callback_data=ccd(
                                             "SHOW_BOOKINGS", wkday)))

            if common.is_booking_time():
                keyboard = [
                    day_subkeyboard,
                    [
                        InlineKeyboardButton("🔂 Prenota una tantum",
                                             callback_data=ccd(
                                                 "BOOKING", "DAY", "Temporary",
                                                 day))
                    ],
                    [
                        InlineKeyboardButton("🔁 Prenota permanentemente",
                                             callback_data=ccd(
                                                 "BOOKING", "DAY", "Permanent",
                                                 day))
                    ],
                    [
                        InlineKeyboardButton("🔚 Esci",
                                             callback_data=ccd("EXIT"))
                    ]
                ]
            else:
                keyboard = [
                    day_subkeyboard,
                    [
                        InlineKeyboardButton("🔚 Esci",
                                             callback_data=ccd("EXIT"))
                    ]
                ]
        else:
            keyboard = []

        return "".join(text), InlineKeyboardMarkup(keyboard)

    else:
        keyboard = [[
            InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))
        ]]

        return f"{day} UberNEST non è attivo.", InlineKeyboardMarkup(keyboard)
Esempio n. 7
0
def booking_handler(bot, update):
    """
    Gestore dei metodi delle prenotazioni. Da questo menù è possibile aggiungere prenotazioni.
    """
    data = separate_callback_data(update.callback_query.data)
    action = data[1]
    chat_id = str(update.callback_query.message.chat_id)

    #
    # Dati in entrata ("BOOKING", "START", mode)
    # Questo menù viene chiamato solo dal menù /prenota e mostra solo i giorni disponibili.
    #
    if action == "START":
        mode = data[2]

        if common.is_booking_time():
            if common.is_sessione():
                bot.edit_message_text(
                    chat_id=chat_id,
                    message_id=update.callback_query.message.message_id,
                    text=f"Scegli la prenotazione.",
                    reply_markup=booking_keyboard(mode, common.today()))
            else:
                bot.edit_message_text(
                    chat_id=chat_id,
                    message_id=update.callback_query.message.message_id,
                    text=f"{common.mode_name(mode)}"
                    f"\n\nSeleziona il giorno della prenotazione.",
                    reply_markup=booking_keyboard(mode,
                                                  common.today(),
                                                  show_bookings=False))
        else:
            bot.edit_message_text(
                chat_id=chat_id,
                message_id=update.callback_query.message.message_id,
                text=f"Mi dispiace, non è possibile effettuare prenotazioni"
                f" tramite UberNEST dalle 02:00 alle 02:15.")
    #
    # Dati in entrata ("BOOKING", "DAY", mode, day)
    # Questo menù viene chiamato rispettivamente dal metodo sopra (BOOKING) e dai visualizzatori
    # delle prenotazioni dei singoli giorni (/lunedi, /martedi, etc...).
    #
    elif action == "DAY":
        mode, day = data[2:4]

        if day not in common.work_days:
            # Caso in cui siamo di sabato o domenica
            day = common.work_days[0]

        if common.is_booking_time():
            bot.edit_message_text(
                chat_id=chat_id,
                message_id=update.callback_query.message.message_id,
                text=f"🗓 {day}"
                f"\n{common.mode_name(mode)}"
                f"\n\nSeleziona il viaggio da prenotare.",
                reply_markup=booking_keyboard(mode, day))
        else:
            bot.edit_message_text(
                chat_id=chat_id,
                message_id=update.callback_query.message.message_id,
                text=f"Mi dispiace, non è possibile effettuare prenotazioni"
                f" tramite UberNEST dalle 02:30 alle 03:30.")
    #
    # Dati in entrata ("BOOKING", "CONFIRM", direction, day, driver, mode)
    # Messaggio finale di conferma all'utente e all'autista. Il metodo calcola se la prenotazione scelta è
    # legale (ovvero che è disponibile spazio nell'auto, che il passeggero non è l'autista e che non si è
    # già prenotato). In caso positivo viene avvisato anche l'autista dell'avvenuta prenotazione
    #
    elif action == "CONFIRM":
        direction, day, driver, mode = data[2:]

        user_keyboard = [[
            InlineKeyboardButton("↩ Indietro",
                                 callback_data=ccd("BOOKING", "START", mode))
        ], [InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))]]

        trip = get_trip(direction, day, driver)
        occupied_slots = len(trip["Permanent"]) + len(trip["Temporary"])
        total_slots = get_slots(driver)

        # Caso in cui l'autista tenta inutilmente di prenotarsi con sè stesso...
        if chat_id == driver:
            user_text = "Sei tu l'autista!"

        # Caso in cui tutti gli slot sono occupati
        elif occupied_slots >= total_slots:
            user_text = "Macchina piena, vai a piedi LOL. 🚶🏻‍♂️"

        # Caso in cui lo stolto passeggero si era già prenotato
        elif chat_id in trip["Temporary"] or chat_id in trip[
                "Permanent"] or chat_id in trip["SuspendedUsers"]:
            user_text = "Ti sei già prenotato in questa data con questa persona!"

        else:
            # Si attende conferma dall'autista prima di aggiungere
            trip_time = trip["Time"]
            slots = str(total_slots - occupied_slots - 1)

            if "Location" in trip:
                location = trip["Location"]
                user_keyboard.insert(0, [
                    InlineKeyboardButton("📍 Mostra sulla mappa",
                                         callback_data=ccd(
                                             "SEND_LOCATION", location))
                ])
            elif direction == "Salita":
                location = "Macchinette"
            else:
                location = "Non definita"

            driver_keyboard = [[
                InlineKeyboardButton("✔ Conferma",
                                     callback_data=ccd("ALERT_USER", "CO_BO",
                                                       direction, day, chat_id,
                                                       mode))
            ]]

            user_text = f"Prenotazione completata. Dati del viaggio:" \
                f"\n\n🚗: [{get_name(driver)}](tg://user?id={driver})" \
                f"\n🗓 {day}" \
                f"\n🕓 {trip_time}" \
                f"\n{common.dir_name(direction)}" \
                f"\n{common.mode_name(mode)}" \
                f"\n📍 {location}" \
                f"\n\nLa prenotazione sarà resa valida al momento della conferma dall'autista."

            driver_text = "Hai una nuova prenotazione: " \
                f"\n\n👤: [{get_name(chat_id)}](tg://user?id={chat_id}) " \
                f"({slots} posti rimanenti)" \
                f"\n🗓 {day}" \
                f"\n🕓 {trip_time}" \
                f"\n{common.dir_name(direction)}" \
                f"\n{common.mode_name(mode)}" \
                f".\n\nPer favore, conferma la presa visione della prenotazione. In caso negativo," \
                f" la prenotazione verrà considerata non valida."

            bot.send_message(
                chat_id=driver,
                text=driver_text,
                reply_markup=InlineKeyboardMarkup(driver_keyboard),
                parse_mode="Markdown")

        bot.edit_message_text(
            chat_id=chat_id,
            message_id=update.callback_query.message.message_id,
            text=user_text,
            reply_markup=InlineKeyboardMarkup(user_keyboard),
            parse_mode="Markdown")
Esempio n. 8
0
def edit_booking(bot, update):
    """
    Questo metodo viene chiamato al momento della richiesta di visione della lista delle prenotazioni da 
    parte dell'utente. Le prenotazione vengono prese tramite query dal metodo search_by_booking presente
    in common.py. Dal menù, una volta selezionata una prenotazione, è possibile cancellarla oppure sospenderla
    a lato utente, ovvero bloccarla per una settimana.
    """
    chat_id = str(update.callback_query.message.chat_id)
    data = separate_callback_data(update.callback_query.data)
    action = data[1]

    #
    #  Comando base chiamato dal metodo prenota. Effettua una query di tutti i viaggi presentandoli
    #  sottoforma di bottoni all'utente.
    #
    if action == "LIST":
        bookings = get_bookings(chat_id)

        keyboard = [[
            InlineKeyboardButton("↩ Indietro",
                                 callback_data=ccd("BOOKING_MENU"))
        ], [InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))]]

        if len(bookings) > 0:
            user_keyboard = []

            for item in bookings:
                direction, day, driver, mode, time = item
                driver_name = get_name(driver)

                if is_suspended(direction, day, driver):
                    tag = " 🚫 Sospesa"
                else:
                    tag = f" 🗓 {day} 🕓 {time}"

                # Aggiunta del bottone
                user_keyboard.append([
                    InlineKeyboardButton(
                        f"🚗 {driver_name.split(' ')[-1]}{tag}\n{common.dir_name(direction)} {common.mode_name(mode)}",
                        callback_data=ccd("EDIT_BOOK", "ACTION", direction,
                                          day, driver, mode))
                ])

            bot.edit_message_text(
                chat_id=chat_id,
                message_id=update.callback_query.message.message_id,
                text=
                "Clicca su una prenotazione per cancellarla o sospenderla.",
                reply_markup=InlineKeyboardMarkup(user_keyboard + keyboard))
        else:
            bot.edit_message_text(
                chat_id=chat_id,
                message_id=update.callback_query.message.message_id,
                text="Mi dispiace, ma non hai prenotazioni all'attivo.",
                reply_markup=InlineKeyboardMarkup(keyboard))
    #
    # Menù disponibile all'utente una volta selezionato un viaggio. I bottoni cambiano a seconda della prenotazione:
    # Temporanea -> solo cancellazione
    # Permanente e sospesa -> sospensione e cancellazione
    #
    elif action == "ACTION":
        direction, day, driver, mode = data[2:]
        keyboard = [
            [
                InlineKeyboardButton("❌ Annulla prenotazione",
                                     callback_data=ccd("EDIT_BOOK", "DELETION",
                                                       direction, day, driver,
                                                       mode))
            ],
            [
                InlineKeyboardButton("↩ Indietro",
                                     callback_data=ccd("EDIT_BOOK", "LIST"))
            ], [InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))]
        ]

        text_string = []
        trip_time = get_time(direction, day, driver)

        if mode == "Permanent":
            keyboard.insert(0, [
                InlineKeyboardButton(
                    "Sospendi prenotazione",
                    callback_data=ccd("EDIT_BOOK", "SUS_BOOK", direction, day,
                                      driver, mode))
            ])

        elif mode == "SuspendedUsers":
            text_string.append(" - SOSPESA dall'utente")
            keyboard.insert(0, [
                InlineKeyboardButton(
                    "Annulla sospensione prenotazione",
                    callback_data=ccd("EDIT_BOOK", "SUS_BOOK", direction, day,
                                      driver, mode))
            ])

        if is_suspended(direction, day, driver):
            text_string.append(" - SOSPESA dall'autista")

        text_string = "".join(text_string)

        bot.edit_message_text(
            chat_id=chat_id,
            message_id=update.callback_query.message.message_id,
            text=f"Prenotazione selezionata: {text_string}\n"
            f"\n🚗 [{get_name(driver)}](tg://user?id={driver})"
            f"\n🗓 {day}"
            f"\n{common.dir_name(direction)}"
            f"\n🕓 {trip_time}"
            f"\n{common.mode_name(mode)}",
            reply_markup=InlineKeyboardMarkup(keyboard),
            parse_mode="Markdown")
    #
    # SUS_BOOK = SUSPEND_BOOKING
    #
    elif action == "SUS_BOOK":
        booking = data[2:]
        mode = booking[3]

        keyboard = [
            InlineKeyboardButton("✔ Sì",
                                 callback_data=ccd("EDIT_BOOK", "CO_SUS_BOOK",
                                                   *booking)),
            InlineKeyboardButton("❌ No",
                                 callback_data=ccd("EDIT_BOOK", "LIST"))
        ]

        if mode == "Permanent":
            message = "Si ricorda che la sospensione di una prenotazione è valida per una sola settimana." \
                      "\n\nSei sicuro di voler sospendere questo viaggio?"

        elif mode == "SuspendedUsers":
            message = "Vuoi rendere di nuovo operativa questa prenotazione?"

        else:
            message = "Errore fatale nel Bot. Contatta il creatore del bot al più presto."

        bot.edit_message_text(
            chat_id=chat_id,
            message_id=update.callback_query.message.message_id,
            text=message,
            reply_markup=InlineKeyboardMarkup([keyboard]))
    #
    # CO_SUS_BOOK = CONFIRM_SUSPEND_BOOKING
    # Il metodo scambia la chiave di un utente da Permanente a SuspendUsers e vice-versa.
    #
    elif action == "CO_SUS_BOOK":
        direction, day, driver, mode = data[2:]
        trip = get_trip(direction, day, driver)

        keyboard = [[
            InlineKeyboardButton("↩ Indietro",
                                 callback_data=ccd("EDIT_BOOK", "LIST"))
        ], [InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))]]

        if mode == "Permanent":
            trip["Permanent"].remove(chat_id)
            trip["SuspendedUsers"].append(chat_id)

            user_message = "Prenotazione sospesa. Verrà ripristinata il prossimo viaggio."
            driver_message = f"[{get_name(chat_id)}](tg://user?id={chat_id})" \
                f" ha sospeso la sua prenotazione permanente" \
                f" per {day.lower()} {common.dir_name(direction)}."

        elif mode == "SuspendedUsers":
            occupied_slots = len(trip["Permanent"]) + len(trip["Temporary"])
            total_slots = get_slots(driver)

            if occupied_slots >= total_slots:
                # Può capitare che mentre un passeggero ha reso la propria prenotazione sospesa,
                # altre persone hanno preso il suo posto.
                bot.edit_message_text(
                    chat_id=chat_id,
                    message_id=update.callback_query.message.message_id,
                    text=f"Mi dispiace, ma non puoi rendere operativa la"
                    f" tua prenotazione in quanto la macchina è ora piena."
                    f"Contatta [{get_name(driver)}](tg://user?id={driver})"
                    f" per risolvere la questione.",
                    reply_markup=InlineKeyboardMarkup(keyboard),
                    parse_mode="Markdown")
                return

            trip["Permanent"].append(chat_id)
            trip["SuspendedUsers"].remove(chat_id)

            user_message = "La prenotazione è di nuovo operativa."
            driver_message = f"[{get_name(chat_id)}](tg://user?id={chat_id})" \
                f" ha reso operativa la sua prenotazione permanente" \
                f" di {day.lower()} {common.dir_name(direction)}."

        else:
            user_message = "Errore fatale nel Bot. Contatta il creatore del bot al più presto."
            driver_message = "Errore: un tuo passeggero ha cercato di sospendere " \
                             "una prenotazione temporanea. Contatta il creatore del bot al più presto."

        bot.edit_message_text(
            chat_id=chat_id,
            message_id=update.callback_query.message.message_id,
            text=user_message,
            reply_markup=InlineKeyboardMarkup(keyboard),
            parse_mode="Markdown")
        bot.send_message(chat_id=driver,
                         text=driver_message,
                         parse_mode="Markdown")
    #
    # Metodo per cancellare per sempre una data prenotazione.
    #
    elif action == "DELETION":
        booking = data[2:]

        keyboard = [
            InlineKeyboardButton("✔ Sì",
                                 callback_data=ccd("EDIT_BOOK", "CO_DEL",
                                                   *booking)),
            InlineKeyboardButton("❌ No",
                                 callback_data=ccd("EDIT_BOOK", "LIST"))
        ]

        bot.edit_message_text(
            chat_id=chat_id,
            message_id=update.callback_query.message.message_id,
            text="Sei sicuro di voler cancellare questo viaggio?",
            reply_markup=InlineKeyboardMarkup([keyboard]))
    #
    # CO_DEL = CONFIRM_DELETION
    #
    elif action == "CO_DEL":
        direction, day, driver, mode = data[2:]
        remove_passenger(direction, day, driver, mode, chat_id)

        keyboard = [[
            InlineKeyboardButton("↩ Indietro",
                                 callback_data=ccd("EDIT_BOOK", "LIST"))
        ], [InlineKeyboardButton("🔚 Esci", callback_data=ccd("EXIT"))]]

        bot.edit_message_text(
            chat_id=chat_id,
            message_id=update.callback_query.message.message_id,
            text="Prenotazione cancellata con successo.",
            reply_markup=InlineKeyboardMarkup(keyboard))
        bot.send_message(
            chat_id=driver,
            text=f"Una prenotazione al tuo viaggio è stata cancellata:"
            f"\n\n👤 [{get_name(chat_id)}](tg://user?id={chat_id})"
            f"\n🗓 {day}"
            f"\n{common.dir_name(direction)}",
            parse_mode="Markdown")