Задать вопрос
  • Aiogram 3 как Установить state для определенного пользователя?

    @twistfire92
    Python backend developer
    Можете заглянуть в исходники aiogram, найти там класс FSMContext, экземпляр которого пробрасывается в вашу функцию, и поизучать это все.
    Один из аргументов функции __init__ этого класса имеет тип StorageKey, который в свою очередь содержит информацию о чате, пользователе, боте и пр.
    Я думаю вам стоит копать в эту сторону, создать руками отдельный инстанс FSMContext (назовем его custom_state), куда передадите отдельный инстанс StorageKey с нужными вам параметрами. Вторым параметром у FSMContext буедет выступать ваш Storage. Либо MemoryStorage, либо RedisStorage (либо у вас свой кастомный какой-то). Туда пробрасывайте тот Storage, который используете.

    И вот уже у этого отдельного инстанса custom_state вызывайте метод set_state()

    P.S. Сам такое не проворачивал, ответ написал опираясь на исходники aiogram. Копайте туда, пробуйте, экспериментируйте.
    Ответ написан
    2 комментария
  • Как создать хэндлер Aiogram для обработки ошибки на Python?

    @twistfire92
    Python backend developer
    Вам тут нужна машина состояний (гуглите aiogram FSM), информации в интернете достаточно много. С ее помощью сможете регистрировать текущее состояние каждого пользователя. Например сейчас пользователь в состоянии ввода цены на товар, поэтому в следующем сообщении которое он введет ожидается число. Если приходится выводить ошибку - выводите и не меняйте состояние пользователя
    Ответ написан
    1 комментарий
  • Как сделать inline кнопку чтобы при нажатии можно было позвонить человеку?

    @twistfire92
    Python backend developer
    Нет такого функционала у API телеги. Разве что сделать какую-то веб прослойку, на которую будет ссылаться кнопка и уже там при открытии вызывать tel:xxxxxxxxxx

    Но это что-то костыльное все равно
    Ответ написан
    Комментировать
  • Не работает инлайн-кнопка после нажатия, как исправить?

    @twistfire92
    Python backend developer
    потому что ваше нажатие на кнопку перехватывает хендлер
    @dp.message()
    async def echo(message: Message):

    Который перехватывает воообще все сообщения, в том числе сообщение "оплатить", которое вы посылаете кнопкой. Просто на это сообщение этот хендлер никак не отреагирует, судя по коду. Поднимите хендлер с функцией оплаты выше.
    Ответ написан
    Комментировать
  • Как сделать так, чтобы при написании команды, начался обратный отсчёт?

    @twistfire92
    Python backend developer
    Программа делает ровно то, что вы ей указали. Берет пользователя, и начинает ему показывать обратный отсчет. Потом берет второго пользователя и делает то же самое. И т.д., пока пользователи не закончатся.

    Если вы хотите чтобы все было одновременно, вам следует одновременно все это запускать. Сначала получше изучите асинхронность, потом напишите асинхронную функцию которая принимает на вход id пользователя, запрашивает его количество секунд и пр. По сути функция должна делать все то, что описано у вас в теле цикла.

    И потом можно попробовать запустить это все, например, через asyncio.gather().

    Сразу предупрежу, что если будет много таких пользователей, есть риск схватить временную блокировку от серверов телеги из-за большого количества запросов. Лучше изучите информацию о том, какие есть ограничения по частоте запросов к серверам телеги.
    Ответ написан
  • Как сделать Многопоточную или асинхронную обработку запросов FASTAPI?

    @twistfire92
    Python backend developer
    Скорее всего у вас где-то вызывается синхронный код в асинхронном ендпоинте. И этот код блокирует event loop.
    Посмотрите пример
    @app.get("/delay")
    async def delay():
        time.sleep(10)
        return {"result": "OK!"}
    
    
    @app.get("/instantly")
    async def instantly():
        return {"result": "OK!"}


    Если сделать запрос на /delay и тут же сделать запрос на /instantly, получится то, о чем я говорю, когда синхронная time.sleep() блокирует цикл событий. Ответ от второго запроса придет только после отработки первого. Обратите внимание, что delay объявлена через async def.

    Исправить это можно двумя способами
    - Использовать асинхронный await asyncio.sleep()
    @app.get("/delay")
    async def delay():
        await asyncio.sleep(10)
        return {"result": "OK!"}

    - Объявить функцию синхронной через def
    @app.get("/delay")
    def delay():
        time.sleep(10)
        return {"result": "OK!"}


    Возможно именно в этом у вас проблема. Найдите синхронный код и либо перепишите на асинхронный вариант, если это возможно (если для обращения в другой сервис вы используете requests, замените на aiohttp или httpx), либо саму функцию ендпоинта сделайте синхронной.
    Ответ написан
  • Проблема с импортами, ошибка, сам не смог решить, как сделать?

    @twistfire92
    Python backend developer
    вот это
    sql = f"SELECT * FROM tg(id, sub) values({id_user}, {sub})"


    перенесите в функцию creat_account (переименуйте в create_account) и удалите строку from bot import sub, id_user
    Ответ написан
    2 комментария
  • Как правильно парсить в телебот и requests?

    @twistfire92
    Python backend developer
    а вы хоть смотрели что попадает в nickname после выполнения nickname = message.text.lower()?
    там по идее всегда будет "/username_search"

    После команды предлагайте пользователю отдельно ввести свой никнейм.
    Воспользуйтесь bot.register_next_step_handler()
    Ответ написан
    2 комментария
  • Вопрос по тг боту на aiogram?

    @twistfire92
    Python backend developer
    у вас видимо код был написан для 2-й версии aiogram.

    Зайдите в документацию, там сразу же показан пример как запускать. executor больше не используется
    Ответ написан
    Комментировать
  • Почему бот дважды выполняет команду (telebot)?

    @twistfire92
    Python backend developer
    Для того, чтобы бот делал рассылку всем пользователям, вам нужно где-то хранить список всех пользователей. Вносить туда новых, когда кто-то новый начинает взаимодействовать с ботом.

    Когда пользователь пишет боту лично, то он находится в чате с самим ботом, где участников 2 - пользователь и бот. Поэтому bot.get_chat_members_count(message.chat.id) выдаст всегда значение 2.
    Если бот будет админом в какой-либо группе, тогда уже выведется количество участников этой группы.

    Вот теперь вы берете и проходите в цикле 2 раза, отправляя в этот чат сообщение.

    Вам же надо где-то хранить все id пользователей, с кем бот взаимодействует. Когда будет отлавливаться нужная команда, проходить в цикле по всем id и отправлять им нужный текст сообщения. Можно из этого списка во время отправки исключить текущего пользователя, чтобы самому не получить сообщение.
    Ответ написан
    5 комментариев
  • Как сохранить машиносостоянии игры :кубик в телеграмме с последующей отправкой кубика в канал?

    @twistfire92
    Python backend developer
    Вместо этого
    lambda message: message.text == ''
    Попробуйте указать так:
    lambda message: message.dice
    Ответ написан
    Комментировать
  • Как перенести aiogram-бота с "long polling" на вебхук?

    @twistfire92
    Python backend developer
    Все с нуля писать скорее всего не придется (Хотя хз как именно у вас все написано). В репозитории aiogram есть пример как можно поднять бота на webhook с использованием aiohttp.

    Я использовал FastAPI как ASGI приложение, которое ловило запрос от сервера телеги и вызывало метод dp.feed_update()
    Ответ написан
    Комментировать
  • Как сделать, чтобы message.text смотрел на только что введеный, а не старый текст?

    @twistfire92
    Python backend developer
    Объект message у вас один всегда, который берется из аргументов функции. Вы его нигде не меняете, поэтому при проверке if message.text == 'Подтвердить': всегда вернется одно и то же значение.
    Если вы хотите ожидать от пользователя нового ввода, стоит перекинуть управление в другую функцию.
    Конкретно в вашем случае лучше воспользоваться register_next_step_handler. И каждый раз прокидывать в него оставшиеся элементы списка из cells_products_data.
    Я не уверен, что register_next_step_handler работает в асинхронном режиме, не юзал telebot в async.
    Изучите этот инструмент подробнее.
    Ответ написан
    Комментировать
  • Как сделать форматирование текста пересланого поста в бота тг?

    @twistfire92
    Python backend developer
    В объекте message текст сообщения и правила форматирования разделены по разным полям - text и entities

    aiogram, к счастью, позволяет получить текст сообщения с уже примененным форматированием в форматах markdown или html

    Поэтому вам стоит работать не с message.text, а с message.html_text, или message.md_text

    Не забудьте потом указать нужный ParseMode при отправке измененного сообщения
    Ответ написан
    Комментировать
  • Как создать реферальную систему Python aiogram 3?

    @twistfire92
    Python backend developer
    В обработчике команды start в объекте message смотрите что пришло в поле text. Там будет что-то типа
    "/start MTIzNDU2Nzg5"
    Отбрасываете "/start ", декодируете оставшееся из Base64, получите id пользователя кому отправлять сообщение.

    Можно при вызове create_start_link значение параметра encode установить False, тогда id реферала кодироваться не будет и никакого декодирования делать не надо будет. Но я бы так не делал.
    Ответ написан
  • Как запретить пользователю писать сообщения в группе на время?

    @twistfire92
    Python backend developer
    Есть вероятность, что сервер телеги ожидает от вас время UTC+0, а вы, возможно передаете время своего часового пояса, (UTC+3 или где вы находитесь), поэтому пользователь блокируется не на 30 секунд, а на 3 часа 30 секунд (опять же, если у вас часовой пояс +3)

    Также в документации Bot API указано, что если время бана меньше 30 секунд или больше 366 дней, то пользователь блокируется навсегда.

    Я бы начал проверку с часовых поясов.

    UPD
    А вы точно правильно используете метод
    restrict_chat_member?
    await bot.restrict_chat_member(chat_id=message.chat.id,
                    user_id=message.reply_to_message.from_user.id,
                    until_date=ban_time,
                    permissions=ChatPermissions(can_send_messages=False)
                    )


    Все разрешения нужно передавать через отдельный объект ChatPermissions в параметре permissions
    Ответ написан
    3 комментария
  • Что нужно поправить в коде на Python, который удаляет последний пост в Телеграм канале?

    @twistfire92
    Python backend developer
    Вы должны сначала получить чат с помощью
    await bot.get_chat(chat_id)
    и только потом у этого объекта вызвать метод fetch_all()

    либо
    chat = await bot.get_chat(chat_id)
    messages = chat.fetch_all()

    либо
    messages = (await bot.get_chat(chat_id)).fetch_all()
    Ответ написан
    Комментировать
  • Как хранить константы в python?

    @twistfire92
    Python backend developer
    Как вариант, можете использовать BaseSettings из Pydantic (Но надо смотреть на версию, во второй отдельная либа для настроек). Получится лишь в ваш класс добавить наследование от BaseSettings. Но если вы не собираетесь прокидывать переменные окружения в настройки, то и ваш вариант вполне рабочий.
    Ответ написан
    Комментировать
  • Как запустить скрипт на Python с использованием сторонних библиотек?

    @twistfire92
    Python backend developer
    В батнике должна быть команда активации виртуального окружения, и только уже потом все остальное
    Ответ написан
    Комментировать
  • Как записать в FSM state свое значение или как словить callback и записать его в state?

    @twistfire92
    Python backend developer
    Уберите global переменную choosed_category

    @router.callback_query(F.data == 'shirt_shorts')
    async def ss(callback: CallbackQuery, state: FSMContext):
        await state.set_data({"choosed_category": shirt_shorts}) # прокидываем в state нужные данные
        # либо await state.update_data(choosed_category=shirt_shorts)
        await callback.answer()
        await callback.message.answer('Ты выбрал(а) категорию Футболка / Шорты \n' + txt.calculation)
        await state.set_state(CalculateCost.choosing_cost)
    
    ....
    
    @router.message(CalculateCost.choosing_cost)
    async def calculate(message: Message, state: FSMContext):
        state_data = await state.get_data()
        choosed_category = state_data["choosed_category]
        ....

    По-хорошему все 4 функции с обработкой калбеков можно сократить в одну, но это уже не тема вопроса
    Ответ написан
    3 комментария