diff --git a/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/filters.py b/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/filters.py new file mode 100644 index 0000000..7c5c304 --- /dev/null +++ b/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/filters.py @@ -0,0 +1,26 @@ +from telebot import types +from telebot.async_telebot import AsyncTeleBot +from telebot.asyncio_filters import AdvancedCustomFilter +from telebot.callback_data import CallbackData, CallbackDataFilter + +calendar_factory = CallbackData("year", "month", prefix="calendar") +calendar_zoom = CallbackData("year", prefix="calendar_zoom") + + +class CalendarCallbackFilter(AdvancedCustomFilter): + key = 'calendar_config' + + async def check(self, call: types.CallbackQuery, config: CallbackDataFilter): + return config.check(query=call) + + +class CalendarZoomCallbackFilter(AdvancedCustomFilter): + key = 'calendar_zoom_config' + + async def check(self, call: types.CallbackQuery, config: CallbackDataFilter): + return config.check(query=call) + + +def bind_filters(bot: AsyncTeleBot): + bot.add_custom_filter(CalendarCallbackFilter()) + bot.add_custom_filter(CalendarZoomCallbackFilter()) diff --git a/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/keyboards.py b/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/keyboards.py new file mode 100644 index 0000000..1aee88c --- /dev/null +++ b/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/keyboards.py @@ -0,0 +1,92 @@ +import calendar +from datetime import date, timedelta + +from filters import calendar_factory, calendar_zoom +from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton + +EMTPY_FIELD = '1' +WEEK_DAYS = [calendar.day_abbr[i] for i in range(7)] +MONTHS = [(i, calendar.month_name[i]) for i in range(1, 13)] + + +def generate_calendar_days(year: int, month: int): + keyboard = InlineKeyboardMarkup(row_width=7) + today = date.today() + + keyboard.add( + InlineKeyboardButton( + text=date(year=year, month=month, day=1).strftime('%b %Y'), + callback_data=EMTPY_FIELD + ) + ) + keyboard.add(*[ + InlineKeyboardButton( + text=day, + callback_data=EMTPY_FIELD + ) + for day in WEEK_DAYS + ]) + + for week in calendar.Calendar().monthdayscalendar(year=year, month=month): + week_buttons = [] + for day in week: + day_name = ' ' + if day == today.day and today.year == year and today.month == month: + day_name = '🔘' + elif day != 0: + day_name = str(day) + week_buttons.append( + InlineKeyboardButton( + text=day_name, + callback_data=EMTPY_FIELD + ) + ) + keyboard.add(*week_buttons) + + previous_date = date(year=year, month=month, day=1) - timedelta(days=1) + next_date = date(year=year, month=month, day=1) + timedelta(days=31) + + keyboard.add( + InlineKeyboardButton( + text='Previous month', + callback_data=calendar_factory.new(year=previous_date.year, month=previous_date.month) + ), + InlineKeyboardButton( + text='Zoom out', + callback_data=calendar_zoom.new(year=year) + ), + InlineKeyboardButton( + text='Next month', + callback_data=calendar_factory.new(year=next_date.year, month=next_date.month) + ), + ) + + return keyboard + + +def generate_calendar_months(year: int): + keyboard = InlineKeyboardMarkup(row_width=3) + keyboard.add( + InlineKeyboardButton( + text=date(year=year, month=1, day=1).strftime('Year %Y'), + callback_data=EMTPY_FIELD + ) + ) + keyboard.add(*[ + InlineKeyboardButton( + text=month, + callback_data=calendar_factory.new(year=year, month=month_number) + ) + for month_number, month in MONTHS + ]) + keyboard.add( + InlineKeyboardButton( + text='Previous year', + callback_data=calendar_zoom.new(year=year - 1) + ), + InlineKeyboardButton( + text='Next year', + callback_data=calendar_zoom.new(year=year + 1) + ) + ) + return keyboard diff --git a/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/main.py b/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/main.py new file mode 100644 index 0000000..392f9ac --- /dev/null +++ b/examples/asynchronous_telebot/callback_data_examples/advanced_calendar_example/main.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +""" +This Example will show you an advanced usage of CallbackData. +In this example calendar was implemented +""" +import asyncio +from datetime import date + +from filters import calendar_factory, calendar_zoom, bind_filters +from keyboards import generate_calendar_days, generate_calendar_months, EMTPY_FIELD +from telebot import types +from telebot.async_telebot import AsyncTeleBot + +API_TOKEN = '1254795383:AAE7gbj1aas4lEDHB1eVuZZhSGPWcH1B5ds' +bot = AsyncTeleBot(API_TOKEN) + + +@bot.message_handler(commands='start') +async def start_command_handler(message: types.Message): + await bot.send_message(message.chat.id, + f"Hello {message.from_user.first_name}. This bot is an example of calendar keyboard." + "\nPress /calendar to see it.") + + +@bot.message_handler(commands='calendar') +async def calendar_command_handler(message: types.Message): + now = date.today() + await bot.send_message(message.chat.id, 'Calendar', + reply_markup=generate_calendar_days(year=now.year, month=now.month)) + + +@bot.callback_query_handler(func=None, calendar_config=calendar_factory.filter()) +async def calendar_action_handler(call: types.CallbackQuery): + callback_data: dict = calendar_factory.parse(callback_data=call.data) + year, month = int(callback_data['year']), int(callback_data['month']) + + await bot.edit_message_reply_markup(call.message.chat.id, call.message.id, + reply_markup=generate_calendar_days(year=year, month=month)) + + +@bot.callback_query_handler(func=None, calendar_zoom_config=calendar_zoom.filter()) +async def calendar_zoom_out_handler(call: types.CallbackQuery): + callback_data: dict = calendar_zoom.parse(callback_data=call.data) + year = int(callback_data.get('year')) + + await bot.edit_message_reply_markup(call.message.chat.id, call.message.id, + reply_markup=generate_calendar_months(year=year)) + + +@bot.callback_query_handler(func=lambda call: call.data == EMTPY_FIELD) +async def callback_empty_field_handler(call: types.CallbackQuery): + await bot.answer_callback_query(call.id) + + +if __name__ == '__main__': + bind_filters(bot) + asyncio.run(bot.infinity_polling()) diff --git a/examples/asynchronous_telebot/CallbackData_example.py b/examples/asynchronous_telebot/callback_data_examples/simple_products_example.py similarity index 100% rename from examples/asynchronous_telebot/CallbackData_example.py rename to examples/asynchronous_telebot/callback_data_examples/simple_products_example.py