Задать вопрос
Ответы пользователя по тегу Telegram
  • Как в telegram bot после каждого сообщения пользователя обновлять время в бд?

    Vindicar
    @Vindicar
    RTFM!
    Почитай про INSERT ... ON CONFLICT UPDATE.
    Ответ написан
    Комментировать
  • Телеграм-бот. Как сохранить второе сообщение от пользователя?

    Vindicar
    @Vindicar
    RTFM!
    У тебя должен быть отдельный обработчик входящих сообщений, а не часть обработчика нажатия на кнопку..
    При этом бот должен помнить, ведёт ли данный пользователь игру в настоящий момент, или нет.
    Ответ написан
  • Из за чего команда 9Abelora выполняется первее чем raspisanie?

    Vindicar
    @Vindicar
    RTFM!
    Изучай документацию, а не "уроки" с ютуба.
    @bot.callback_query_handler(func=lambda call: True)
    def callback_inline(call):
       ...

    func принимает функцию, которая должна по параметру call (сведения о нажатии кнопки) определить, будет ли данный обработчик обрабатывать это нажатие. Соответственно, функция вида lambda call: True всегда будет отвечать "да, я буду обабатывать!".

    При этом бот вызовет первый "согласившийся" обработчик, и ТОЛЬКО его. Как следствие, наличие одного обработчика с func=lambda call: True блокирует все нижележащие обработчики, так как этот "всеядный" обработчик будет брать на себя все нажатия кнопок (независимо от того, понимает ли он их). До остальных обработчиков дело просто не дойдёт.

    Чтобы это разрулить, надо прописывать не lambda call: True, а функцию, которая реально будет различать, какой набор кнопок у пользователя, и какая кнопка была нажата. Самый простой способ это сделать - сделать этакую иерархию в строке call.data. Например:
    9a.tomorrow
    9a.week
    9a.today
    10a.tomorrow
    10a.week
    10a.today

    Тогда ты сможешь прописать обработчики вида:
    @bot.callback_query_handler(func=lambda call: call.data.startswith('10a.'))
    def callback_inline_for_10a(call):
       ...  # тут обрабатываем кнопки для 10А
    
    @bot.callback_query_handler(func=lambda call: call.data.startswith('9a.'))
    def callback_inline_for_9a(call):
       ...  # тут обрабатываем кнопки для 9А


    Ну а создание кнопок, соответственно, будет иметь вид
    item1 = types.InlineKeyboardButton("Домашнее задание на завтра", callback_data='10a.tomorrow')
    Ответ написан
    4 комментария
  • Не отправляются фотографии пользователю в библеотеке telebot, что делать?

    Vindicar
    @Vindicar
    RTFM!
    def raspisanie(message):
    def raspisanie(call):
    Ничего странного не замечаешь?
    Ответ написан
  • Как отправить сообщений в определенное время telebot?

    Vindicar
    @Vindicar
    RTFM!
    телебот - это синхронная библиотека. Он не предусматривает длительной работы обработчиков.
    Так что тебе придётся выносить ожидание момента (тот же пакет schedule) в отдельный поток.
    Но я без понятия, безопасно ли обращаться к методам telebot из других потоков.
    Ответ написан
  • Возможно-ли добавить в бота телеграмм (pyTelegramBotAPI), подставление картинки поверх основной картинки?

    Vindicar
    @Vindicar
    RTFM!
    Возможно.
    За готовым кодом - на фриланс. Сюда - с конкретными вопросами по реализации.
    Ответ написан
  • Как обслуживать юзеров по очереди телебот?

    Vindicar
    @Vindicar
    RTFM!
    global user_id
    Ну как бы вот виновник. Глобальные переменные. Они общие на всего бота и на всех пользователей. Если тебе нужно дифференцировать пользователей - делай это сам.
    Делай хранилище "ключ-значение", где ключ - ID пользователя, значение - хранимые для этого пользователя данные. При обработке сообщения читай ID пользователя, доставай из хранилища данные, и уже сообразно им обрабатывай сообщение.
    Таким хранилищем может быть простой словарь (если не нужно сохранять состояние между перезапусками бота), БД или ещё что.

    Не знаю, есть ли в telebot реализация Finite State Machine, но обычно для реализации сценариев используют её. Идея та же - для каждого юзера храним его текущее состояние (шаг в сценарии) и ассоциированные с ним данные.
    Ответ написан
    2 комментария
  • Как реализовать запись следующего сообщения?

    Vindicar
    @Vindicar
    RTFM!
    На гитхабе вариант с несколькими стейтсами, а мне нужен один.

    В приведённом примере явно два состояния - ожидание фразы "ввести имя" и ожидание собственно имени. Одним тут не обойдёшься. Или изменяй сценарий (нафиг вообще вводить фразу "ввести имя"?) или используй два состояния.
    Ответ написан
    Комментировать
  • Как создать список из картинок и текста и выводить рандомным способом?

    Vindicar
    @Vindicar
    RTFM!
    Ну про random.choice() ты знаешь. В чём проблема-то?
    Если нужно соответствие картинки и текста, то просто храни текст и картинку одним элементом списка - например, через кортеж.
    tarot_list = [
        ('image1.jpg', 'Текст 1'),
        ('image2.jpg', 'Текст 2'),
    ]

    Тогда потом просто делаешь:
    image, text = random.choice(tarot_list)
    и вперёд!
    Ответ написан
  • Бот обратной связи на Aiogram?

    Vindicar
    @Vindicar
    RTFM!
    Ну во-первых, "не получилось" - это, конечно, офигенно детальное и полезное описание проблемы.

    Во-вторых, я подозреваю, что дело вот в этом:
    photo=message.photo[0].file_id
    Наверняка если к сообщению не приложено фото, коллекция photo пуста, тогда попытка обращения к нулевому элементу выкинет исключение, так как этого нулевого элемента просто нет. Проверяй, есть ли вообще что-то в message.photo.
    Ответ написан
    Комментировать
  • Как в reply_markup добавить больше переменных с копками?

    Vindicar
    @Vindicar
    RTFM!
    bot.send_photo(message.chat.id, photo, " Выберите нужную функцию:",
    parse_mode="html", reply_markup=tg, info)

    reply_markup=tg - аргумент, переданный по имени
    info - аргумент, переданный позиционно.
    Питон не позволяет указывать позиционные аргументы ПОСЛЕ именованных. Укажи для info имя аргумента, в который ты хочешь передать это значение, по аналогии с reply_markup= или parse_mode=.
    Ответ написан
    Комментировать
  • Как убрать лишние знаки?

    Vindicar
    @Vindicar
    RTFM!
    Ещё один не выучил основы языка, но пытается работать с БД.

    fectchone() возвращает кортеж, в твоём случае кортеж с одним элементом. Скобки - это строковое представление кортежа. Как вытащить значение из кортежа - читай по ссылке.

    Кортежи, списки и словари - это вообще азы языка. Их надо знать, и узнавать с первого взгляда.
    Ответ написан
    Комментировать
  • Как ипортировать функции из файлов?

    Vindicar
    @Vindicar
    RTFM!
    Ещё один товарищ не учил Питон, но рвётся написать божественного бота...

    Когда ты импортируешь файл (модуль), этот модуль выполняется - практически так же, как если бы ты его запустил непосредственно. Различие есть, но небольшое. Теперь посмотрим на твои файлы.
    В первом файле ты объявляешь переменную bot. Она существует в пространстве имён первого файла (модуля).
    Если ты в нём делаешь import second_file, в нём тоже присутствует создание переменной bot - в локальном пространстве имён этого модуля. Это две разные переменные, и два разных экземпляра класса Telebot.
    Поэтому когда ты выполняешь в одном файле bot.run() (ну или как там бот запускается), ты запускаешь только один экземпляр. Второй остаётся неактивированным, и всё, что к нему привязано, не работает.

    Тебе надо как-то передать переменную bot во-второй файл, не нарвавшись при этом на циклический импорт (чтобы не было "первый импортирует второй, а второй - первый").
    Тут поможет ещё один простой факт: в питоне всё - операторы. Т.е. объявление функции - это оператор. Его можно помещать куда угодно, внутрь любого блока программы: внутрь if, внутрь цикла, внутрь другой функции. Он выполнится при выполнении соответствующего блока.
    Так что ты можешь завернуть свои обработчики из второго файла в функцию, принимающую ссылку на bot. А потом импортировать эту внешнюю функцию в первый файл и там её вызвать.
    #второй файл, second_file.py
    import telebot
    from telebot import types
    # эта функция создаст все обработчики и зарегистрирует их в предоставленном боте
    # вызывай её строго один раз за скрипт
    def register_handlers(bot):
        # а тут уже пошли обработчики
        @bot.message_handler(commands=['start'])
        def start(message):
            markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
            btn0 = types.KeyboardButton(' Каталог фильмов')
            btn1 = types.KeyboardButton(" Каталог фильмов")
            btn2 = types.KeyboardButton(' Случайный фильм')
            btn3 = types.KeyboardButton(' Предложить фильм')
            markup.add(btn0, btn1, btn2, btn3)
            bot.send_message(message.from_user.id, ' Привет, {0.first_name}. Я Kinomorph - бот, с которым ты можешь найти интересный фильм для просмотра вечером\n \n Если у тебя есть номер или название фильма, ввести его можно прямо сейчас'.format(message.from_user), reply_markup=markup)
    
    # любой код, который не должен исполняться при импорте, оформляй так:
    if __name__ == '__main__':   # переменная __name__ содержит имя, под которым импортируется модуль
        print('Этот код выполнится ТОЛЬКО если файл запущен напрямую.')
        print('Он не выполнится при импорте файла.')


    # первый файл, main.py
    import telebot
    import config
    import second_file  # модуль импортируется - в нём __name__ будет равно "second_file", а не "__main__"
    
    # инициализация
    bot = telebot.TeleBot(config.Token)
    second_file.register_handlers(bot)  # тут вызывается импортированная функция
    Ответ написан
    Комментировать
  • Почему не работает bot_func.stop(Client, module Pyrogram)?

    Vindicar
    @Vindicar
    RTFM!
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    Зачем?!
    Если у тебя бот асинхронный, просто сделай саму функцию GetUserByUsername() async.
    Ответ написан
  • Не выполгяется последняя часть кода @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 комментарий
  • Как обратится к функции вне handler?

    Vindicar
    @Vindicar
    RTFM!
    global resault_func
    resault_func = fi(fil)

    Примерно так и обращайся.
    Ответ написан
    1 комментарий
  • Цикл для обработчика кнопок?

    Vindicar
    @Vindicar
    RTFM!
    def handle_button(call_data: str):
            try:
                fileid = int(call_data) - 1  # определяем id файла по значению call_data
            except ValueError:
                return
            markup = InlineKeyboardMarkup()
            bttn_contact = (InlineKeyboardButton(text = " Связаться с менеджером", callback_data = "contact")) 
            markup.add(bttn_contact)
            bttn_home = (InlineKeyboardButton(text = " Начало", callback_data = "home"))
            markup.add(bttn_home)
            with open(f'data/{fileid}_info.txt', 'r', encoding = "utf-8") as file:
               content = file.read()
            # if тут не нужен, сработает и без него.
            for x in range(0, len(content), 4095):
                bot.send_message(call.message.chat.id,content[x:x+4095],reply_markup=markup)

    Ну а в обработчике просто дергаешь handle_button(call.data).
    Ответ написан
    Комментировать
  • Как сделать так, чтобы бот телеграмм пересылал данные, которые ввел пользователь в другой аккаунт?

    Vindicar
    @Vindicar
    RTFM!
    Смотри в сторону Finite State Machine.
    Если коротко, твой бот должен для каждого пользователя помнить, на каком этапе он находится, и обрабатывать события соответственно.
    "Я получил сообщение от Васи. Вася сейчас на этапе ввода имени. Значит, нужно записать текст сообщения как имя, попросить ввести номер, и перевести Васю на этап ввода номера."
    Многие библиотеки для чатботов уже имеют ту или иную реализацию FSM, как раз для реализации таких вот сценариев. Читай документацию на ту библиотеку, которую ты собираешься использовать.
    Если у неё этого нет, или эта реализация тебе почему-то не подходит, то можно попробовать наколхозить её самому. Как я уже говорил, всё, что реально нужно - для каждого пользователя помнить, на каком этапе он находится.
    Ответ написан
    Комментировать
  • Как правильно одновременно запустить двух 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 комментария