Приостановить отправку сообщений пока пользователь не нажмет InlineKeyboardButton
Пользователь вводит множество значений, и чтобы не отправлять сразу тонну сообщений нужно подтверждать отправку каждого следующего нажатием inline кнопки. Код рабочий, убрал все лишнее чтобы был лучше понятен сценарий. Комментариями обозначил основные шаги и где требуется подтверждение от пользователя. Есть какой-то способ приостановить отправку сообщений в цикле и возобновить только при нажатии inline кнопки?
import os
from aiogram.dispatcher import FSMContext
from aiogram import Bot, Dispatcher, executor, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher.filters.state import StatesGroup, State
bot = Bot(token=os.environ["TOKEN"])
dispatcher = Dispatcher(bot, storage=MemoryStorage())
class Searches(StatesGroup):
by_id = State()
@dispatcher.message_handler(state='*', commands='cancel')
async def cancel_state(message: types.Message, state: FSMContext):
if await state.get_state():
await state.finish()
await message.reply("Поиск был отменён.")
@dispatcher.message_handler(commands="search")
async def answer_search_message(message: types.Message):
find_by_id_button = types.InlineKeyboardButton("по ID", callback_data="by_id")
keyboard = types.InlineKeyboardMarkup().row(find_by_id_button)
await message.answer("Выбери тип поиска", parse_mode="HTML", reply_markup=keyboard)
@dispatcher.callback_query_handler(text="by_id")
async def callback_id(callback: types.CallbackQuery):
await callback.message.answer("Введи ID, разделяя их запятой")
await Searches.by_id.set()
@dispatcher.message_handler(state=Searches.by_id)
async def find_by_id(message: types.Message, state: FSMContext):
ids_from_message = [item for item in range(5)] # получаю список id из сообщения
for index, item in enumerate(ids_from_message):
photo, caption, url = ("https://www.google.ru/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", "текст документа", "https://www.example.org/") # получаю по id какие-то данные
button_to_site = types.InlineKeyboardButton("Подробнее на сайте", url)
keyboard = types.InlineKeyboardMarkup().row(button_to_site)
if len(ids_from_message) > index + 1: # если это не последний id, то показываю кнопку "Следующий результат"
keyboard.add(types.InlineKeyboardButton("Следующий результат", callback_data="show_next"))
await message.answer_photo(photo=photo, caption=caption, parse_mode="HTML", reply_markup=keyboard)
# тормознуть цикл тут, ожидая нажатия кнопки "Следующий результат"
else:
await message.answer_photo(photo=photo, caption=caption, parse_mode="HTML", reply_markup=keyboard)
await state.finish()
executor.start_polling(dispatcher)
Ответы (1 шт):
Автор решения: Brain Drill
→ Ссылка
Вот мой вариант решния этой проблемы. Суть его в том, что можно сохранить некие данные в используемое хранилище (в данном примере локальное). И потом по чуть-чуть их отправлять пользователю, когда тот нажимает кнопку.
import os
from aiogram.dispatcher import FSMContext
from aiogram import Bot, Dispatcher, executor, types
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from aiogram.dispatcher.filters.state import StatesGroup, State
def get_record_by_id(doc_id):
# тут как-то обработался id и что-то вернул
return "https://www.google.ru/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png", "текст документа", "https://www.example.org/"
bot = Bot(token=os.environ["TOKEN"])
storage = MemoryStorage()
dispatcher = Dispatcher(bot, storage=storage)
class Searches(StatesGroup):
by_id = State()
@dispatcher.message_handler(state='*', commands='cancel')
async def cancel_state(message: types.Message, state: FSMContext):
if await state.get_state():
await state.finish()
await message.reply("Поиск был отменён.")
@dispatcher.message_handler(commands="search")
async def answer_search_message(message: types.Message):
find_by_id_button = types.InlineKeyboardButton("по ID", callback_data="by_id")
keyboard = types.InlineKeyboardMarkup().row(find_by_id_button)
await message.answer("Выбери тип поиска", parse_mode="HTML", reply_markup=keyboard)
@dispatcher.callback_query_handler(text="by_id")
async def callback_id(callback: types.CallbackQuery):
await callback.message.answer("Введи ID, разделяя их запятой")
await Searches.by_id.set()
await callback.answer()
@dispatcher.message_handler(state=Searches.by_id)
async def find_by_id(message: types.Message, state: FSMContext):
user_id = message.from_user.id
ids_from_message = [item for item in range(5)]
photo, caption, url = get_record_by_id(ids_from_message[0])
button_to_site = types.InlineKeyboardButton("Подробнее на сайте", url)
keyboard = types.InlineKeyboardMarkup().row(button_to_site)
if len(ids_from_message) > 1:
del ids_from_message[0]
await storage.set_data(user=user_id, data={"ids_to_send": ids_from_message})
keyboard.add(types.InlineKeyboardButton("Следующий результат", callback_data="show_next"))
await message.answer_photo(photo=photo, caption=caption, parse_mode="HTML", reply_markup=keyboard)
else:
await message.answer_photo(photo=photo, caption=caption, parse_mode="HTML", reply_markup=keyboard)
await state.finish()
@dispatcher.callback_query_handler(state=Searches.by_id, text="show_next")
async def callback_id(callback: types.CallbackQuery, state: FSMContext):
user_id = callback.from_user.id
chat_id = callback.message.chat.id
data = await storage.get_data(user=user_id)
photo, caption, url = get_record_by_id(data["ids_to_send"][0])
button_to_site = types.InlineKeyboardButton("Подробнее на сайте", url)
keyboard = types.InlineKeyboardMarkup().row(button_to_site)
if len(data["ids_to_send"]) > 1:
del data["ids_to_send"][0]
await storage.set_data(user=user_id, data={"ids_to_send": data["ids_to_send"]})
keyboard.add(types.InlineKeyboardButton("Следующий результат", callback_data="show_next"))
await bot.send_photo(chat_id=chat_id, photo=photo, caption=caption, parse_mode="HTML", reply_markup=keyboard)
else:
await bot.send_photo(chat_id=chat_id, photo=photo, caption=caption, parse_mode="HTML", reply_markup=keyboard)
await state.finish()
await callback.answer()
executor.start_polling(dispatcher)