telebot, telegram_bot_calendar decorators

Viewed 312

I am trying to display the calendar using the telegram_bot_calendar package after pressing the button, but the code does not work, the code below is highlighted. Apparently, I don't fully understand how decorators work.

import datetime
from telegram_bot_calendar import DetailedTelegramCalendar, LSTEP

tb = telebot.TeleBot('TOKEN')

usertable = dict() # list of usernames that the / menu press responds to
usertable['USERNAME'] = True 



@tb.message_handler(commands=['start', 'help'])
def send_welcom(message):
    tb.reply_to(message, f'Хей, {message.from_user.first_name}')
    
@tb.message_handler(commands=['menu'])
def send_welcom(message):
    if message.chat.username in usertable:
        tb.send_message(message.from_user.id, f'Hi, {message.from_user.username}')
        markup = telebot.types.InlineKeyboardMarkup()
        markup.add(telebot.types.InlineKeyboardButton(text='Call calendar', callback_data=1))
        markup.add(telebot.types.InlineKeyboardButton(text='Second', callback_data=2))
        markup.add(telebot.types.InlineKeyboardButton(text='third', callback_data=3))
        tb.send_message(message.chat.id, text="Выбери пункт меню:", reply_markup=markup)
            
        @tb.callback_query_handler(func=lambda call: True)
        def query_handler(call):

            tb.answer_callback_query(callback_query_id=call.id, text='Обработка...')
            answer = ''
            if call.data == '1':

                #the beginning of the non-working part
                
                @tb.callback_query_handler(func=lambda m: call.data == '1') # should cause the choice of the year
                def start(m):
                    calendar, step = DetailedTelegramCalendar().build()
                    tb.send_message(m.message.chat.id, f"Select {LSTEP[step]}", reply_markup=calendar)

                @tb.callback_query_handler(func=DetailedTelegramCalendar.func())
                def next(c):
                    
                    result, key, step, action = DetailedTelegramCalendar().process(c.data)
                
                    if not result and key:
                        tb.edit_message_text(f"Select {LSTEP[step]}", 
                                              c.message.chat.id,
                                              c.message.message_id,
                                              reply_markup=key)
                    elif result:
                        tb.edit_message_text(f"You selected {result}",
                                              c.message.chat.id,
                                              c.message.message_id)
                
                #the end of the non-working part

                
                answer = f'Resolt'
            elif call.data == '2':
                answer = 'Second Resolt'
            elif call.data == 'Third Resolt':
                answer = 'ещё что-то!'

            tb.send_message(call.message.chat.id, answer)
            

    else: tb.send_message(message.from_user.id, f'Access closed, {message.from_user.username}')

@tb.message_handler(content_types=['text'])
def get_text_messages(message):
    if message.text.lower() == 'привет':
        tb.reply_to(message, f'Привет, {message.from_user.username}')
    else: tb.send_message(message.from_user.id, 'Press /menu')

    
tb.polling(none_stop=True)

working code, calling the calendar with the /menu:

@bot.message_handler(commands=['menu'])
def start(m):
    calendar, step = DetailedTelegramCalendar().build()
    bot.send_message(m.chat.id,
                     f"Select {LSTEP[step]}",
                     reply_markup=calendar)


@tb.callback_query_handler(func=DetailedTelegramCalendar.func())
def cal(c):
    result, key, step = DetailedTelegramCalendar().process(c.data)
    if not result and key:
        tb.edit_message_text(f"Select {LSTEP[step]}",
                              c.message.chat.id,
                              c.message.message_id,
                              reply_markup=key)
    elif result:
        tb.edit_message_text(f"You selected {result}",
                              c.message.chat.id,
                              c.message.message_id)

any suggestions how i can do this?

1 Answers

The reason that your code is not working is that you are declaring handlers inside handlers. This approach is incorrect!

Here is corrected code:

import telebot
from telebot.types import InlineKeyboardButton as ikb, InlineKeyboardMarkup as ikm
from telegram_bot_calendar import DetailedTelegramCalendar, LSTEP

tb = telebot.TeleBot('TOKEN')

usertable = dict()
usertable['USERNAME'] = True

@tb.callback_query_handler(func=DetailedTelegramCalendar.func())
def next_page(c):
    result, key, step = DetailedTelegramCalendar().process(c.data)
    m = c.message

    if not result and key:
        tb.edit_message_text(f"Select {LSTEP[step]}", m.chat.id, m.message_id, reply_markup=key)
    elif result:
        tb.edit_message_text(f"You selected {result}", m.chat.id, m.message_id)


@tb.callback_query_handler(func=lambda call: True)
def query_handler(call):
    answer = ''
    if call.data == '1':
        calendar, step = DetailedTelegramCalendar().build()
        tb.send_message(call.message.chat.id, f"Select {LSTEP[step]}", reply_markup=calendar)
        answer = 'Result'
    elif call.data == '2':
        answer = 'Second Result'
    elif call.data == 'Third Result':
        answer = 'Something!'

    tb.answer_callback_query(call.id, answer)


@tb.message_handler(commands=['menu'])
def send_welcome(m):
    user = m.from_user
    if m.chat.username in usertable:
        tb.send_message(user.id, f'Hi, {user.username}')
        markup = ikm()
        markup.add(
            ikb(text='Call calendar', callback_data=1),
            ikb(text='Second', callback_data=2),
            ikb(text='third', callback_data=3)
        )
        tb.send_message(m.chat.id, text="Select menu:", reply_markup=markup)
    else:
        tb.send_message(user.id, f'Access closed, {user.username}')


tb.polling(none_stop=True)

You can see that each handler is written separately, not inside each other. And the handler @tb.callback_query_handler(func=lambda m: call.data == '1') is removed, because there is already if condition for that case inside @tb.callback_query_handler(func=lambda m: call.data == '1') handler:

if call.data == '1':


Hope that helps :)

Related