Как создать и передать переменную с user_id из одного handler'а в другой? (Python, Aiogram)

Рейтинг: 0Ответов: 1Опубликовано: 28.03.2023

Дана функция отзывов:

•По команде /fb пользователю отправляется сообщение

@dp.message_handler(Command('fb'))
async def fb(message: types.Message):
    await message.answer('Напишите, что хотите отправить автору')
    await fb_states.waiting_for_fb.set()

•После отправки отзыва присылается сообщение пользователю и админу

@dp.message_handler(state=fb_states.waiting_for_fb)
async def state1(message: types.Message, state: FSMContext):
    markup = InlineKeyboardMarkup(row_width=2,
                                  inline_keyboard=[
                                      [
                                          InlineKeyboardButton(text='Ответить', callback_data='answer'),
                                          InlineKeyboardButton(text='Прочитано', callback_data='read')
                                      ]
                                  ])
    user = message.from_user.username
    answer = message.text
    await state.finish()
    await message.answer('Отзыв отправлен!')
    for admin in admins:
        try:
            await dp.bot.send_message(chat_id=admin, text=f'Поступил отзыв от @{user}:\n'
                                                          f'"{answer}"', reply_markup=markup)
        except Exception as err:
            logging.exception(err)

•По нажатию у админа на кнопку "Ответить" присылается сообщение

@dp.callback_query_handler(text='answer', state=fb_states.waiting_for_answer)
async def state2(call: types.CallbackQuery):
    await call.message.edit_reply_markup()
    await call.message.answer('Напишите ответ на отзыв')
    await fb_states.waiting_for_answer.set()

•После отправления админу приходит сообщение, но пользователю не приходит

@dp.message_handler(state=fb_states.waiting_for_answer)
async def state3(message: types.Message, state: FSMContext):
    answer = message.text
    await state.finish()
    await message.answer('Ответ отправлен!')
    try:
        await dp.bot.send_message(chat_id=user_id, text=f'Поступил ответ на отзыв:\n'
                                                        f'"{answer}"')
    except Exception as err:
        logging.exception(err)

class fb_states(StatesGroup):
    waiting_for_fb = State()
    waiting_for_answer = State()

Нужно каким-то образом, чтобы во 2-ом handler'е создавалась переменная с user_id, которая потом бы использовалась в последнем handler'е для отправки сообщение пользователю. Помогите пожалуйста это реализовать!

Ответы

▲ 1Принят

UРД: Ах да, чуть не забыл, вам не обязательно использовать целиком мой код, основная идея была в том, как передать и получить ID user'a.


Мой вариант будет отличаться, я написал его не исходя из вашего кода. В моем случае отсутствует FSM автоматы.

Первое, что я сделал это кнопки:

#Кнопка отправить, и отменить(удалить) отправку
def sendBtn():
    send = InlineKeyboardButton("Send", callback_data="send")
    cancel = InlineKeyboardButton("Cancel", callback_data="cancel")
    keyboard = InlineKeyboardMarkup(row_width=1)
    keyboard.add(send, cancel)
    return keyboard 

Следующим шагом давайте распишем логику этих кнопок:

@dp.callback_query_handler(text = "send")
async def sendToadm(call:types.CallbackQuery):
    id_user = call.from_user.id #Самое интересное - мы передадим в сообщении админу id юзера, которое мы без труда потом достанем.
    username = call.from_user.username #у вас был юзер нейм, пусть для красоты тут тоже будет.
    await call.bot.send_message(id_admin, f'ID: "{id_user}"\nUsername: "{username}"\n{call.message.text}')

@dp.callback_query_handler(text = "cancel")
async def delmsg(call:types.CallbackQuery):
    #Тут просто удаляю сообщение, если пользователь не захотел отправлять, или ошибся в написанном.
    await call.bot.delete_message(message_id=call.message.message_id, chat_id=call.message.chat.id)

Самое вкусное:

@dp.message_handler()
async def sendTouser(message:types.Message):
    if(message.reply_to_message): #Когда админ увидит сообщение от пользоваетля, ему будет достаточно просто ответить(reply) на него. и сразу отправить через бота юзеру
        user_id = message.reply_to_message.text.split('"')[1] #Я говорил выше, самое интересное это id usera, которое мы получили вместе с сообщением
        await bot.send_message(user_id, f'from admin:\n{message.text}')#Отправка вашего сообщения от бота - пользователю
    else:
        await message.reply(message.text, reply_markup=sendBtn()) #Этот фрагмент я отображу на скриншоте

Принцип работы:

  1. После того, как я отправил сообщение я сразу получил возможность отправить или отменить message:

введите сюда описание изображения

  1. Когда пользователь отправил админу сообщение, оно приходит ему в такой форме:

введите сюда описание изображения

  1. Из вышеуказанного мне достаточно просто сделать reply_to_message и произойдет магия(из-за split):

введите сюда описание изображения

  1. Финал:

введите сюда описание изображения


Я сразу хочу обратить ваше !ВНИМАНИЕ! т.к. я общался и за админа и за юзера, все происходило в одном чате!, соответственно при транспонировании моего кода под ваш вы должны все тщательно проверить, сходиться ли все по id.


Как по мне, идеальный вариант(с учетом допиливания всех фич) для отзывов, или сообщений админам и тд. Просто и без пафоса. И не нужен лишний автомат.