Тугмаҳо ва callback-ҳо
Чаро ба бот тугма лозим аст
Фармонро бояд дар хотир дошт ва навишт, тугмаро бошад бо чашм интихоб кардан мумкин аст. Тугмаҳо барои меню, тасдиқ ва дидани рӯйхати дароз қулайанд. Навиштаи намоён ва амал маълумоти гуногунанд: навиштаро тарҷума кардан мумкин аст, рамзи дохилии амал бошад доимӣ мемонад.
Дар aiogram клавиатураҳои inline, ки ба паёми мушаххас пайвастанд, ва клавиатураҳои одӣ зери майдони вуруд ҳастанд. Пахши тугмаи матнии одӣ паёмро бо матни тугма мефиристад. Пахши тугмаи inline бо callback_data рӯйдоди алоҳидаи CallbackQuery месозад. Тугмаи дорои url ба ҷойи ин пайвандро мекушояд.
1. Аз тугмаҳо ба қаторҳо
InlineKeyboardBuilder ёварест, ки тугмаҳоро ҷамъ карда, ба қаторҳо мегузорад. button тугма илова мекунад; text — навишта, callback_data — маълумот барои бот. Сатрҳои монанди pick:1 протоколи мо ҳастанд: aiogram ба онҳо худкор маъно намедиҳад.
adjust андозаи қаторҳоро муайян мекунад ва as_markup() объекти клавиатураро барои параметри reply_markup ҳангоми фиристодани паём месозад. Дар ин ҷо қатори аввал ду тугма ва боқимондаҳо яктогӣ доранд.
from aiogram.utils.keyboard import InlineKeyboardBuilder
builder = InlineKeyboardBuilder()
for n in range(1, 6):
builder.button(text=str(n), callback_data=f"pick:{n}")
builder.adjust(2, 1)
for row in builder.as_markup().inline_keyboard:
print([(button.text, button.callback_data) for button in row])
Натиҷа:
[('1', 'pick:1'), ('2', 'pick:2')]
[('3', 'pick:3')]
[('4', 'pick:4')]
[('5', 'pick:5')]
Андозаи охир дар adjust(2, 1) то охир такрор мешавад. Бо adjust(2, 1, repeat=True) тамоми пайдарпаии андозаҳо такрор мешуд. Агар тугмаҳо аз андозаи қатор камтар бошанд, қатор нопурра мешавад. Builder вазифаи махсуси тугмаро намефаҳмад: барои амали махсус қатори алоҳидаро худатон бояд пешбинӣ кунед.
Фиристодан дар коркардкунандаи тайёр чунин аст: await message.answer(text, reply_markup=builder.as_markup()). Танҳо сохтани нишонагузорӣ онро ба Telegram намефиристад.
2. Ҳангоми пахшкунӣ чӣ меояд
callback.data маълумоти дохилии тугма, callback.from_user шахси пахшкарда ва callback.message одатан паёми дорои клавиатураро дар бар мегирад. Ин паёми матнии нав нест. Нозири router.callback_query лозим аст, масалан бо филтри F.data.startswith("pick:").
Callback ду амали мустақил дорад. Таҳрир бо edit_text паёмро дар чат иваз мекунад. Тасдиқ бо callback.answer() нишонаи интизориро мебандад; агар матн диҳед, огоҳӣ ҳам пайдо мешавад. Ҳар ду амалро сохта, майдонҳояшонро бе фиристодан ба шабака мебинем.
from aiogram.types import CallbackQuery, Chat, Message, User
message = Message(message_id=5, date=0,
chat=Chat(id=42, type="private"), text="A")
callback = CallbackQuery(id="q1", from_user=User(
id=9, is_bot=False, first_name="Mina"), chat_instance="demo",
data="pick:4", message=message)
edit = callback.message.edit_text("B")
answer = callback.answer()
print(callback.data, callback.from_user.id)
print(type(edit).__name__, edit.message_id, edit.text)
print(type(answer).__name__, answer.callback_query_id)
Натиҷа:
pick:4 9
EditMessageText 5 B
AnswerCallbackQuery q1
Дар дархости таҳрир ID-и паёми 5 ва дар тасдиқ ID-и пахшкунии q1 нигоҳ дошта шудааст. Дар коркардкунандаи воқеӣ ҳар ду амал бо await интизор мешаванд. Таҳрир тасдиқро иваз намекунад: мизоҷи Telegram ҷавоби худи callback-ро интизор аст.
Callback аз ҳолати inline метавонад message надошта бошад; барои он inline_message_id истифода мешавад. Дар масъалаҳои курс паём дастрас аст, вале дар коди умумӣ аввал мавҷудият ва дастрасии онро месанҷанд.
3. Маълумоти дорои навъ
Ҳангоми split(":")-и дастӣ ҷойи майдонҳоро омехтан ё табдили ададро фаромӯш кардан осон аст. CallbackData форматро як бор муайян мекунад: префикс оилаи тугмаҳоро ҷудо мекунад ва аннотатсияҳои майдонҳо навъҳоро муайян мекунанд. Мисоли навбатӣ менюи ҳуҷҷатҳост, на ҳалли пурраи масъала.
from aiogram.filters.callback_data import CallbackData
from aiogram.utils.keyboard import InlineKeyboardBuilder
class MenuCb(CallbackData, prefix="menu"):
section: str
item: int
value = MenuCb(section="docs", item=8)
builder = InlineKeyboardBuilder()
builder.button(text="8", callback_data=value)
packed = builder.as_markup().inline_keyboard[0][0].callback_data
restored = MenuCb.unpack(packed)
print(packed)
print(restored.section, restored.item, type(restored.item).__name__)
Натиҷа:
menu:docs:8
docs 8 int
pack() сатрро месозад, unpack() онро баръакс ҷудо мекунад. Builder объекти фабрикаро худкор баста метавонад. Пас аз ҷудокунӣ item навъи int дорад. Дар ин формат қимати майдон набояд ҷудокунандаи : дошта бошад.
Барои сабт MenuCb.filter(F.section == "docs") истифода мешавад. Параметри callback_data: MenuCb дар коркардкунанда майдонҳои ҷудошударо мегирад. Ин филтр маълумоти бегона ё нодурустро рад мекунад, вале ҳуқуқи корбарро барои тағйири объекти мушаххас намесанҷад. Инро худи бот аз рӯи ID-и корбар ва маълумоти худ месанҷад.
4. Саҳифаҳо ва ҳаҷми маълумот
Аввал индекс, баъд намоиш: дар барнома саҳифаҳо аксар вақт аз сифр ҳисоб мешаванд, ба инсон бошад рақам аз як нишон дода мешавад. Барои индекси page оғози буриш page * size аст. Танҳо интихоби порчаро нишон медиҳем, бе сохтани клавиатураи тайёри саҳифабандӣ.
Маҳдудияти дигар: callback_data аз 1 то 64 байт ҷой мегирад, на ҳарф. Дарозиро пас аз рамзгузории UTF-8 санҷед. Ҳарфи ӯ ду байт ҷой мегирад.
items = list("ABCDEFG")
size = 3
page = 1
print(items[page * size:(page + 1) * size])
print(len("ӯ".encode("utf-8")))
print(len(("ӯ" * 33).encode("utf-8")))
Натиҷа:
['D', 'E', 'F']
2
66
Дар саҳифаи индекси 1 унсурҳои чорум, панҷум ва шашум ҳастанд. Ду сатри охир нишон медиҳанд, ки чаро 33 аломати кириллӣ аллакай аз ҳудуди маълумоти тугма зиёд аст. Дар тугма амал ва идентификатори кӯтоҳро нигоҳ доред, матни дарозро бошад дар маълумоти бот.
Дар дохил чӣ мегузарад
Клавиатура ҳамчун қисми паём ба Telegram фиристода мешавад. Мизоҷ онро мекашад ва ҳангоми пахшкунӣ ID-и пахш, корбар ва callback_data-ро ба бот бармегардонад. Router коркардкунандаи мувофиқи callback-ро интихоб мекунад. Он мавҷудияти объект ва ҳуқуқро санҷида, маълумотро иваз мекунад, ҳангоми зарурат паёмро таҳрир мекунад ва пахшкуниро тасдиқ мекунад.
Хатоҳои маъмул ва ислоҳ
- Гӯш кардани рӯйдоди дигар.
@router.message(F.text == "1")callback-и тугмаи inline-ро намегирад.router.callback_queryсабт карда, маълумотро санҷед, на навиштаи тугмаро. - Фаромӯш кардани тасдиқ. Танҳо
await callback.message.edit_text(...)паёмро тағйир медиҳад, вале нишонаи интизорӣ мемонад.await callback.answer()-ро, аз ҷумла дар шохаҳои рад, даъват кунед. - Шумораи тугма ҳисобидани adjust.
builder.adjust(2)тугмаҳои зиёдатиро тоза намекунад: ҳама мемонанд, дутоӣ дар қатор. Барои ҷойгиркунии дигар андозаи лозими қаторҳоро диҳед. - Гузоштани матни дароз дар callback_data.
callback_data="ӯ" * 3366 байт аст ва мувофиқ нест. ID-и кӯтоҳ диҳед;len(data.encode("utf-8"))-ро чен кунед. - Бовар кардан ба ID-и кӯҳна.
items[rid]пас аз тозакунӣKeyErrorмедиҳад. Мавҷудият ва ҳуқуқро санҷед ва барои объекти мавҷуднабуда ба callback огоҳии фаҳмо диҳед.
Ёддошт
| Унсур | Вазифа |
|---|---|
button(text=..., callback_data=...) |
Навишта ва маълумоти дохилӣ |
adjust(...) |
Андозаи қаторҳо |
as_markup(), reply_markup |
Клавиатураи тайёр ва додани он ба паём |
router.callback_query |
Коркарди пахшкуниҳо |
callback.data, callback.from_user |
Амал ва корбари пахшкарда |
edit_text(...) |
Тағйири паём |
await callback.answer() |
Тасдиқи ҳар пахшкунӣ |
CallbackData, pack, unpack, filter |
Формат, бастабандӣ, ҷудокунӣ ва филтри маълумот |