Ответы пользователя по тегу Боты
  • Не выполгяется последняя часть кода @bot.callback_query_handler(func=lambda call:True) def callback2(call): почему и как исправить?

    Vindicar
    @Vindicar
    RTFM!
    @bot.callback_query_handler(func=lambda call:True)
    func говорит боту, когда вызывать обработчик. Бот вызывает только ОДИН обработчик (первый подходящий).
    func=lambda call:True означает, что обработчик должен вызываться для ВСЕХ кнопок.
    Научись различать обработчики по call.data. Например, пусть у одной группы кнопок data начинается с "foo.", а у другой - с "bar.".
    item = types.InlineKeyboardButton('4', callback_data='foo.question1')
    item2 = types.InlineKeyboardButton('3', callback_data='foo.question2')

    gotov = types.InlineKeyboardButton('Готов', callback_data='bar.gotov')

    Тогда ты сможешь прописать два обработчика:
    @bot.callback_query_handler(func=lambda call:call.data.startswith('foo.'))

    и
    @bot.callback_query_handler(func=lambda call:call.data.startswith('bar.'))


    Разумеется, вместо foo и bar можно придумать свои префиксы, в том числе многоуровневые (типа callback_data='questions.q1.answer1').
    Ответ написан
    1 комментарий
  • Как правильно одновременно запустить двух Telegram ботов одной программой на Python?

    Vindicar
    @Vindicar
    RTFM!
    Ну потому что ты фигню написал.
    th_bot = Thread(target=pyrobot(), args=())
    th_userbot = Thread(target=aiobot(), args=())

    Ты пытаешься запустить в качестве потока значение, возвращаемое функцией pyrobot(). А так как она уходит в цикл и значения не возвращает, то далее ничего не происходит. До вызова конструктора Thread() дело не доходит. С aiobot() аналогично.

    Еще раз:
    pyrobot() - вызов функции
    pyrobot - ссылка на функцию

    EDIT:
    Оба бота - асинхронные на базе asyncio, им для работы нужен цикл-реактор (event loop). Вообще не факт, что хорошая идея запускать их в потоках.
    Тут есть два варианта, сразу даже не скажу, что проще.
    Вариант А, лобовой: каждый бот создаёт своё собственные реактор через asyncio.new_event_loop(), потом задаёт его как текущий для своего потока через asyncio.set_event_loop(loop). Если ботам не требуется взаимодействовать, то это может быть проще. Если требуется... будут проблемы. Два реактора в одной программе - это не хорошо.

    Вариант Б, адекватный:
    И вызов app.run(), и вызов executor.start_polling(dp, skip_updates=True) скорее всего под капотом создают асинхронную функцию (корутину), и запускают её в реакторе. Тогда ты можешь обойтись без потоков, заставив обоих ботов работать на одном реакторе. Нужно будет зарыться в доки, или даже глянуть исходники.

    Например, для пирограмма написано такое:
    When calling this method (app.run()) without any argument it acts as a convenience method that calls start(), idle() and stop() in sequence. It makes running a single client less verbose.

    Т.е. вместо вызова app.run() ты можешь изменить код так:
    async def pyrobot():  # обрати внимание, теперь функция асинхронная!
        print("pyro started")
        @app.on_message(filters.chat("some_chat"))
        async def print_pyrogram():
            print("Pyrogram")
        # это вместо вызова app.run(), как написано в доках.
        await app.start()
        try:
            await app.idle()
        finally:
            await app.end()

    Затем делаешь аналогичный трюк с aiobot(). Нужно посмотреть в доках на аиограм, как именно.

    И потом запускаешь обоих ботов кодом вида...
    asyncio.run(asyncio.gather(pyrobot(), aiobot()))
    Ответ написан
    3 комментария
  • Как отправлять текст соответствующий картинке в телеграм боте на Python?

    Vindicar
    @Vindicar
    RTFM!
    1. вынеси random.choice(os.listdir('test')) в переменную, например, img
    2. используй os.path.splitext(os.path.basename(img))[0], чтобы получить имя файла картинки без расширения
    3. Не забудь отправить файл через photo = open('test/' + img, 'rb')
    4. PROFIT
    Ответ написан
    2 комментария
  • Бот рандомно выбирает вопрос, но проверяет по ответам для 1 вопроса, как исправить?

    Vindicar
    @Vindicar
    RTFM!
    if x == 1:
        @bot.message_handler(content_types="text")
        def send(message):
            ...

    Так работать НЕ будет. Ты явно не очень понимаешь, что делаешь.

    1. Должна быть только одна функция, декорированная как @bot.message_handler(content_types="text"). Если их несколько, отработате только одна.

    2. Ты должен хранить сведения:
    - Какой вопрос был последним задан тому или иному пользователю
    - Какие вопросы были уже заданы тому или иному пользователю
    В рамках обучения их можно хранить в словаре, но в реальном боте потребуется постоянное хранилище (например, БД), в котором эти сведения пережили бы перезапуск бота

    3. Внутри обработчика @bot.message_handler ты должен получить ID пользователя, отправившего сообщение, взять из описанного выше хранилища номер последнего заданного вопроса (если есть), и уже на основании этого номера судить о том, правильный ли ответ.
    Ответ написан
  • Как заставить дискорд бота запустить песню?

    Vindicar
    @Vindicar
    RTFM!
    Ну тебе бот пишет прямым текстом где он ищет библиотеку:
    OSError: dlopen(opus, 0x0006): tried: 'opus' (no such file), '/usr/local/lib/opus' (no such file), '/usr/lib/opus' (no such file), '/Users/similization/Programming/python/discord_bot/opus' (no such file)

    Найди, куда именно установился опус, и создай символическую ссылку на библиотеку по одному из указанных путей. Лучше всего по последнему, я полагаю.
    Ответ написан
  • Как передать апдейт телеграм боту о том что парсер обновил БД?

    Vindicar
    @Vindicar
    RTFM!
    Вариантов много. Самый простой - храни в БД время обновления (например, время, когда была добавлена запись), и пусть его бот периодически проверяет. Хорошо работает в том плане, что БД может обновляться разными источниками, бот о них знать не обязан. Но вносит лаг между обновлением данных и реакцией бота. Да и бот базу понапрасну дергает.

    Так как в тегах postgre, почитай про команду NOTIFY. Она вроде примерно про то же самое.

    Также есть вариант с сокетом - бот слушает UDP-сокет, парсер на него посылает пакет с оповещением. Плюс в том, что оповещать может любая программа, которая может до этого сокета достучаться.
    Ответ написан
    1 комментарий
  • Почему не принимает сообщение?

    Vindicar
    @Vindicar
    RTFM!
    text=(int)
    Это не будет работать.
    Учи, как пользоваться реализацией FSM (finite state machine) в aiogram.
    Ответ написан
    Комментировать
  • Как вывести данные из массива в сообщение?

    Vindicar
    @Vindicar
    RTFM!
    for product in select_db():
        @dp.callback_query_handler(text=product['name_but'])
        async def pole(message: types.message):
            await bot.send_message(message.from_user.id, product['desk'], reply_markup=but.nav_button)

    Ты делаешь глупость.
    Просто потому, что после того, как этот код отработает, созданные тобой копии обработчика pole() останутся, и будут мешать.
    Используй один, более общий обработчик callback_query_handler, и в нём уже смотри, какой текст тебе пришёл, какой пользователь его отправил, и что с этим текстом надо делать.
    Ответ написан
    1 комментарий
  • Как сделать условие в SQLite Python?

    Vindicar
    @Vindicar
    RTFM!
    Ну так у тебя второй запрос запршивает всех пользователей, без условия.
    А вообще приведённый код не имеет смысла и не должен работать вообще никак.
    for i in cursor.fetchone("SELECT ID FROM user_info WHERE RANK = '1'"):

    Ты перебираешь столбцы в первой строке (fetchone), для которой RANK = '1'. Это при том, что запрос возвращает тебе только один столбец - ID. А ещё метод fetchone() не принимает параметров. Ты пропустил вызов execute()?

    Потом ты почему-то берёшь 0й символ этого столбца. Если он равен 1 (а он не будет равен 1, так как это символ, а не число).
    Потом ты перебираешь всех пользователей, и отправляешь им сообщения (при этом у тебя в вызове send_message() две опечатки - в имени переменной и незакрытая скобка).

    А ещё у тебя отступы кривые - почему for i с отступом?

    В общем, по такой бредятине понять, в чём дело, нереально.
    Ответ написан
    4 комментария
  • Как ответить пользователю через бота?

    Vindicar
    @Vindicar
    RTFM!
    Хранить где-то (в БД, например) какое сообщение закрытого чата соответствует какому пользователю. При получении сообщения-ответа в закрытом чате узнать ID отвеченного сообщения, посмотреть в базе, какой пользователь отправил оригинал, переслать текст этому пользователю.
    Ответ написан
  • Ошибка TypeError: 'tuple' object is not callable?

    Vindicar
    @Vindicar
    RTFM!
    result = cursor.execute("SELECT id, name, price, colvo FROM tovars").fetchone()
    return result

    fetchone() возвращает либо None, либо кортеж (tuple). Значит, get_item() возвращает None (если такой строки нет) или tuple (если она есть).

    result = get_item()
    tgitem = result()

    Ты пытаешься вызвать (call) кортеж (tuple), как будто это функция. Так нельзя, и питон тебе так и говорит:
    TypeError: 'tuple' object is not callable

    Читай учебник, что такое кортежи.
    Ответ написан
    9 комментариев
  • Пишу бота в тг, выдается ошибка 'main', как решить?

    Vindicar
    @Vindicar
    RTFM!
    pprint(data)
    data = r.json()

    Тебя порядок не смущает?
    Ответ написан
    3 комментария
  • Почему не работает как положено aioschedule в телеграм боте?

    Vindicar
    @Vindicar
    RTFM!
    aioschedule работает с корутинами. trackingStart() - не корутина, а обычная синхронная процедура.
    Ответ написан
    1 комментарий
  • Как вывести баланс в телеграм боте?

    Vindicar
    @Vindicar
    RTFM!
    Значит у тебя нет записи в БД для этого юзера. Ты add_user() точно выполнял для него?
    Ответ написан
  • Как вызвать асинхронную функцию с синхронной функции?

    Vindicar
    @Vindicar
    RTFM!
    Если твой вызов асинхронной функции сводится к реакции на завершение выполнения синхронного кода, то используй run_in_executor(), он позволяет выносить код хоть в процесс, хоть в поток (смотря какой executor используешь), и оборачивает его в обычную асинхронную корутину, которую можно await-ить. Для простых случаев есть asyncio.to_thread(), но тут вопрос в природе выполняемого кода. CPU-bound код на питоне будет занимать GIL, тормозя остальные потоки (эта общая болезнь для потоков в питоне).

    А вообще есть асинхронные версии селениума, типа aioselenium или selenium-async. Можешь попробовать одну из них.

    Если же тебе нужно вызвать асинхронную корутину именно посреди синхронного кода в другом потоке, то run_coroutine_threadsafe() может помочь. Пример из доков на питон.
    async def coro_func():
         return await asyncio.sleep(1, 42)
    
    # Later in another OS thread:
    
    future = asyncio.run_coroutine_threadsafe(coro_func(), loop)
    # Wait for the result:
    result = future.result()
    Ответ написан
  • Почему выдаёт ошибку с @bot?

    Vindicar
    @Vindicar
    RTFM!
    Блин, еще раз - текст ошибки угадывать нужно?
    Вбил в гугл "@bot.callback_query_handlers", он подсказывает, что наверно нужно "@bot.callback_query_handler" (в конце нет буквы S).
    Ответ написан
    Комментировать
  • Как или с помощью чего сделать Telegram бота, который выполняет скрипт по заданному времени?

    Vindicar
    @Vindicar
    RTFM!
    aioschedule посмотри.
    Ответ написан
    Комментировать
  • Бот не отправляет переменные?

    Vindicar
    @Vindicar
    RTFM!
    'Карта: " + str(a) + " " + str(b) + " " + str(c) + " " + str(d) +"\nCVV: " + str(e))'

    У тебя внешние кавычки одни, а внутренние другие. Так что весь этот фрагмент - одна строковая константа, а двойные кавычки внутри - просто символы.
    К слову, научись использовать f-строки.
    f"Карта: {a} {b} {c} {d}\nCVV: {e}"
    Ответ написан
    Комментировать
  • Как научить телеграмм бота присылать рандомные изображения из облака?

    Vindicar
    @Vindicar
    RTFM!
    1. Научить бота получать список доступных URL изображений (в виде БД или списка)
    2. Научить бота выбирать случайное изображение из списка
    3. Научить бота отдавать URL

    Ну или если не хочется светить URL пользователю
    3. Научить бота скачивать изображение по URL
    4. Научить бота пересылать скачанное изображение как вложение

    Это всё, что я могу посоветовать, так как ты не озаботился детализировать задачу.
    Ответ написан
    2 комментария