Aiogram из одной и той же функции не отрабатывает корректно
Бот собирает данные и предоставляет пользователю выбор обратной связи: почта, мобильная и телеграмм. Если переходить по кнопкам, то конечный этап - функция last_funс
, где пользователю дается выбор подтвердить введенные данные, начать заново или отменить. Если выбирать мобильный номер или почту все корректно отрабатывается, а через телеграмм - зависает и вообще нечего не делает.
import hendlers
import re
from aiogram import types
from aiogram.types import InlineKeyboardMarkup, InlineKeyboardButton, ReplyKeyboardMarkup, KeyboardButton
from create import bot, Dispatcher, dp
from aiogram.contrib.fsm_storage.memory import MemoryStorage
from keyboard import (trc_button, check_invoice, service_selection, callback, send_phone, language_button,
confirm_inline_keyboard)
from aiogram.dispatcher.filters import Text
from aiogram.dispatcher import FSMContext
from aiogram.dispatcher.filters.state import State, StatesGroup
from hendlers.mail365 import send_mail
from hendlers.handler_start import start_message
class FSMAccounting(StatesGroup):
sec = State()
service = State()
bin = State()
type_document = State()
agreement = State()
period = State()
callback = State()
contact = State()
last = State()
# Стартовые пропустим
# предлагается выбор инлайн кнопками "Телефон" "Емаил" "Телеграмм"
async def reconciliation_periods(message: types.CallbackQuery, state=FSMContext):
async with state.proxy() as data:
data['period'] = message.text
await FSMAccounting.next()
await bot.send_message(
message.from_user.id,
'? Каким способом Вам будет удобно получить обратную связь?',
reply_markup=callback
)
# Проверка на правельность ввода телефона и почты
async def callback_choice(callback_query: types.CallbackQuery, state: FSMContext):
await state.update_data(callback=callback_query.data)
if callback_query.data == 'Телефон':
# Кнопка для отправки номера телефона
keyboard = ReplyKeyboardMarkup(resize_keyboard=True, one_time_keyboard=True)
contact_button = KeyboardButton("Добавить ?", request_contact=True)
keyboard.add(contact_button)
await FSMAccounting.contact.set()
await bot.send_message(
callback_query.from_user.id,
'Введите свой номер телефона в формате (7 xxx xxxxxxx) или нажмите кнопку ниже:',
reply_markup=keyboard,
)
elif callback_query.data == 'E-mail':
await FSMAccounting.contact.set()
await bot.send_message(
callback_query.from_user.id,
'Введите адрес электронной почты:'
)
# При нажатии кнопки Telegram в FSM уходит его контак и ID в FSM
elif callback_query.data == 'Telegram':
user_id = callback_query.from_user.id
await state.update_data(contact=f"@{callback_query.from_user.username or 'Без имени'} (ID: {user_id})")
await last_func(callback_query, state) # тут все уходит в финальную фукцию
# Впроверка вводимых данных на правильный ввод телефона и почты
async def user_contact(message: types.CallbackQuery, state: FSMContext):
element = await state.get_data()
print('user_contact')
if element.get('callback') == 'Телефон':
print('phone')
if message.contact:
phone_number = message.contact.phone_number
await state.update_data(contact=phone_number)
elif not message.text.isdigit() or len(message.text) < 10:
await bot.send_message(
message.from_user.id,
'Введите свой номер телефона в формате (7 xxx xxxxxxx)'
)
return
else:
await state.update_data(contact=message.text)
elif element.get('callback') == 'E-mail':
print('mail')
if not re.match(r"^[^@]+@[^@]+\.[^@]+$", message.text):
await bot.send_message(message.from_user.id, 'Введите корректный E-mail')
return
await state.update_data(contact=message.text)
print('state.get_data')
await last_func(message, state) # тут все уходит в финальную фукцию
# финальная функция в которой вылетают кнопки подтверждения вводимой информации или повторного ввода,
# почему то если прийти сюда через кнопку Telegram FSM затыкается и дальше не идет
async def last_func(message: types.CallbackQuery, state: FSMContext):
element = await state.get_data()
confirm_keyboard = InlineKeyboardMarkup(row_width=2)
confirm_keyboard.add(
InlineKeyboardButton("✅ Подтвердить", callback_data="confirm"),
InlineKeyboardButton("? Заново", callback_data="restart"),
InlineKeyboardButton("❌ Отмена", callback_data="cancel")
)
print(f'{message}\n\n {element}')
await bot.send_message(
message.from_user.id,
f"Ваши данные:\n"
f"ТРЦ: {element.get('sec', 'Не указано')}\n"
f"Услуга: {element.get('service', 'Не указано')}\n"
f"БИН: {element.get('bin', 'Не указано')}\n"
f"Тип документа: {element.get('type_document', 'Не указано')}\n"
f"Номер договора: {element.get('agreement', 'Не указано')}\n"
f"Период сверки: {element.get('period', 'Не указано')}\n"
f"Контакт: {element.get('contact', 'Не указано')}\n\n"
f"Вы подтверждаете введённые данные?",
reply_markup=confirm_keyboard
)
# финишь FSM отправка данных на почту
@dp.callback_query_handler(Text(equals="confirm"), state=FSMAccounting.contact)
async def confirm_data(callback_query: types.CallbackQuery, state: FSMContext):
print('confirm')
element = await state.get_data()
await bot.send_message(
callback_query.from_user.id,
"<strong>Ваши данные отправлены:</strong>",
reply_markup=language_button, parse_mode='HTML'
)
send_mail(element)
await state.finish()
await callback_query.answer("Данные подтверждены.")
# стоп FSM старт ее по новой
@dp.callback_query_handler(Text(equals="restart"), state=FSMAccounting.contact)
async def restart_fsm(callback_query: types.CallbackQuery, state: FSMContext):
await state.finish()
await FSMAccounting.sec.set()
await bot.send_message(
callback_query.from_user.id,
"? Пожалуйста, укажите ТРЦ:",
reply_markup=trc_button
)
await callback_query.answer("Начнем заново.")
# отмена
@dp.callback_query_handler(Text(equals="cancel"), state=FSMAccounting.contact)
async def cancel_fsm(callback_query: types.CallbackQuery, state: FSMContext):
await state.finish()
await bot.send_message(
callback_query.from_user.id,
"❌ Действие отменено. Вы можете начать заново.",
reply_markup=language_button
)
await callback_query.answer("Действие отменено.")
def handler_message_accounting(dp: Dispatcher):
dp.register_callback_query_handler(callback_choice, state=FSMAccounting.callback)
dp.register_message_handler(user_contact, state=FSMAccounting.contact, content_types=['text', 'contact'])
dp.register_callback_query_handler(confirm_data, Text(equals="confirm"), state=FSMAccounting.contact)
dp.register_callback_query_handler(restart_fsm, Text(equals="restart"), state=FSMAccounting.contact)
dp.register_callback_query_handler(cansel, Text(equals='cancel', ignore_case=True), state='*')