Задать вопрос
  • Не понимаю почему с плагином Telebot, бот при нажатие кнопки Stats не пишет статы которые написаны в коде?

    @theurus
    отправлять сюда код надо внутри специальных тегов что бы он нормально отображался

    <code lang="python">
    @bot.message_handler(content_types=['text'])
    def buttonforpers(message):
    ...
    </code>
  • Как хостить телеграм бота дома?

    @theurus
    белый ип не нужен, он дает небольшой бонус по лимитам, больше размер пересылаемых файлов итп
    постоянно работающий сервер тоже - если тебя устроит бот который не работает когда ты спишь(твой комп выключен)
  • Как сделать, чтобы ответы появлялись только после ввода вопроса пользователем?

    @theurus
    добавь хранилище состояний в начале

    STATE = {}
    и добавляй туда юзеров от которых ожидается вопрос

    выходов из функции может быть несколько

    в обработчике текстов проверяем что ввели, если Магический шар то сохраняем состояние STATE[message.from_user.id] = 'stage1' отправляем сообщение и выход return

    если нет то проверка if message.from_user.id in STATE and STATE[message.from_user.id] == 'stage1':
    и тут у нас уже вопрос в message.text, можно ответить на него и удалить состояние
    del STATE[message.from_user.id]
  • Как реализовать общение юзеров через телеграмм бот?

    @theurus
    в телеграме можно создать группу с подгруппами и бот может создавать новую подгруппу для каждого юзера, что бы там отдельно можно было общаться менеджеру с юзером вместо которого выступает бот64d61681c10bf763552650.png
  • Как реализовать общение юзеров через телеграмм бот?

    @theurus
    надо будет добавлять какой то маркер в сообщения которые приходят менеджеру от бота, что бы понятно было от какого пользователя и куда обратно отправлять
  • Как реализовать общение юзеров через телеграмм бот?

    @theurus
    дальше администратор должен указать боту кто тут менеджер (на самом деле)

    ну а дальше всё просто. бот знает от кого пришло сообщение, и умеет отправлять сообщения любому кто с ним поздоровался
  • Как сделать функцию горячих клавиш в telegram боте?

    @theurus
    сделай отдельную функцию для создания клавиатур, так проще будет

    bot.send_message(callback.message.chat.id, 'выберите мастера', reply_markup=get_keyboard('main_menu'))

    вместо того чтоб посылать новое сообщение с клавиатурой каждый раз можно менять текущее

    bot.edit_message_text

    def get_keyboard(kbd: str) -> telebot.types.InlineKeyboardMarkup:
        """создает и возвращает клавиатуру по текстовому описанию
        'chat' - клавиатура для чата
        'mem' - клавиатура для команды mem, с кнопками Забудь и Скрой
        'hide' - клавиатура с одной кнопкой Скрой
        ...
        """
        if kbd == 'chat':
            markup  = telebot.types.InlineKeyboardMarkup(row_width=5)
            button1 = telebot.types.InlineKeyboardButton("➡", callback_data='continue_gpt')
            button2 = telebot.types.InlineKeyboardButton("♻️", callback_data='forget_all')
            button3 = telebot.types.InlineKeyboardButton("", callback_data='erase_answer')
            button4 = telebot.types.InlineKeyboardButton("", callback_data='tts')
            button5 = telebot.types.InlineKeyboardButton("", callback_data='translate_chat')
            markup.add(button1, button2, button3, button4, button5)
            return markup
        elif kbd == 'mem':
            markup  = telebot.types.InlineKeyboardMarkup()
            button1 = telebot.types.InlineKeyboardButton("Стереть историю", callback_data='clear_history')
            button2 = telebot.types.InlineKeyboardButton("Скрыть", callback_data='erase_answer')
            markup.add(button1, button2)
            return markup
        elif kbd == 'hide':
            markup  = telebot.types.InlineKeyboardMarkup()
            button1 = telebot.types.InlineKeyboardButton("Скрыть", callback_data='erase_answer')
            markup.add(button1)
            return markup
  • Как идентифицировать темы форума?

    @theurus Автор вопроса
    вроде разобрался. как то всё контр интуитивно

    обычное сообщение отправленное в тему в группе почему то имеет свойство reply_to_message и в нем is_topic_message и message.reply_to_message.message_thread_id

    ответ на такое сообщение НЕ имеет message.reply_to_message но имеет is_topic_message и message.message_thread_id

    и похоже что это всё что нужно было

    остается не понятным что означает message_thread_id во всех остальных случаях Ж)

    def get_topic_id(message: telebot.types.Message) -> str:
        """
        Get the topic ID from a Telegram message.
    
        Parameters:
            message (telebot.types.Message): The Telegram message object.
    
        Returns:
            str: '[chat.id] [topic.id]'
        """
    
        chat_id = message.chat.id
        # topic_id = 'not topic'
        topic_id = 0
    
        if message.reply_to_message and message.reply_to_message.is_topic_message:
            topic_id = message.reply_to_message.message_thread_id
        elif message.is_topic_message:
            topic_id = message.message_thread_id
    
        # bot.reply_to(message, f'DEBUG: [{chat_id}] [{topic_id}]')
    
        return f'[{chat_id}] [{topic_id}]'
  • Почему не перехватываются медиа сообщения?

    @theurus
    медиа ловится отдельно

    @bot.message_handler(content_types = ['video', 'video_note'])
    def handle_video(message: telebot.types.Message):
    """Обработчик видеосообщений. Сюда же относятся новости и репосты с видео"""

    if message.from_user.id == тут_ид наверное лучше внутрь обработчика запихнуть, хотя тебе виднее
  • Возможно установить Windows 11?

    @theurus
    на рутрекере есть образы с пофикшеным инсталятором. ставится и работает даже на 775 сокете, 2 ядра 2 гига и вин11 Ж)
  • Как в питоне обеспечить контроль целосности данных?

    @theurus
    можно создать свой класс реализующий байты и вываливающий любые ошибки какие хочешь

    вообще такой тип уже есть

    >>> a=(300).to_bytes(length=1)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    OverflowError: int too big to convert
    >>> a=(300).to_bytes(length=2)
    >>> a
    b'\x01,'
    >>>
  • Какой Linux поставить на ноут, которому лет 20?

    @theurus
    никакой линукс не сможет гонять DOOM/SAMP лучше чем божественная хепешечка. она ушла непобежденной и навсегда останется в наших сердцах
  • Как запустить синхронную функцию параллельно телеграм боту на aiogram?

    @theurus
    я не смог Ж) в итоге у меня бот работает на telebot и обычных тредах без какой либо асинхронщины

    вот он с примером одной из функций. а твою функцию можно запустить так же но при запуске указать ее как onstartup

    #!/usr/bin/env python3
    
    import threading
    import telebot
    
    import cfg
    
    
    bot = telebot.TeleBot(cfg.token, skip_pending=True)
    
    
    # до 40 одновременных потоков для чата с гпт и бингом
    semaphore_talks = threading.Semaphore(40)
    
    
    
    class ShowAction(threading.Thread):
        """Поток который можно остановить. Беспрерывно отправляет в чат уведомление об активности.
        Телеграм автоматически гасит уведомление через 5 секунд, по-этому его надо повторять.
    
        Использовать в коде надо как то так
        with ShowAction(chat_id, 'typing'):
            делаем что-нибудь и пока делаем уведомление не гаснет
        
        """
        def __init__(self, chat_id, action):
            """_summary_
    
            Args:
                chat_id (_type_): id чата в котором будет отображаться уведомление
                action (_type_):  "typing", "upload_photo", "record_video", "upload_video", "record_audio", 
                                  "upload_audio", "upload_document", "find_location", "record_video_note", "upload_video_note"
            """
            super().__init__()
            self.actions = [  "typing", "upload_photo", "record_video", "upload_video", "record_audio",
                             "upload_audio", "upload_document", "find_location", "record_video_note", "upload_video_note"]
            assert action in self.actions, f'Допустимые actions = {self.actions}'
            self.chat_id = chat_id
            self.action = action
            self.is_running = True
            #self.start()
            self.timerseconds = 1
            
        def run(self):
            while self.is_running:
                bot.send_chat_action(self.chat_id, self.action)
                n = 50
                while n > 0:
                    time.sleep(0.1)
                    n = n - self.timerseconds
    
        def stop(self):
            self.timerseconds = 50
            self.is_running = False
    
        def __enter__(self):
            self.start()
            return self
    
        def __exit__(self, exc_type, exc_val, exc_tb):
            self.stop()
    
    
    
    
    @bot.message_handler(content_types = ['voice'])
    def handle_voice(message: telebot.types.Message): 
        """Автоматическое распознавание текст из голосовых сообщений"""
        thread = threading.Thread(target=handle_voice_thread, args=(message,))
        thread.start()
    def handle_voice_thread(message: telebot.types.Message):
        """Автоматическое распознавание текст из голосовых сообщений"""
    
        my_log.log_media(message)
    
        with semaphore_talks:
            # Создание временного файла 
            with tempfile.NamedTemporaryFile(delete=False) as temp_file:
                file_path = temp_file.name
            # Скачиваем аудиофайл во временный файл
            file_info = bot.get_file(message.voice.file_id)
            downloaded_file = bot.download_file(file_info.file_path)
            with open(file_path, 'wb') as new_file:
                new_file.write(downloaded_file)
            # Распознаем текст из аудио
            # если мы не в привате и в этом чате нет блокировки автораспознавания то показываем активность
            if not (message.chat.id in BLOCKS and BLOCKS[message.chat.id] == 1) or message.chat.type == 'private':
                with ShowAction(message.chat.id, 'typing'):
                    if cfg.stt == 'vosk':
                        text = my_stt.stt(file_path)
                    elif cfg.stt == 'whisper':
                        text = my_whisper.get_text(file_path)
            else:
                if cfg.stt == 'vosk':
                    text = my_stt.stt(file_path)
                elif cfg.stt == 'whisper':
                    text = my_whisper.get_text(file_path)
    
            os.remove(file_path)
    
            # если мы не в привате и в этом чате нет блокировки автораспознавания
            if not (message.chat.id in BLOCKS and BLOCKS[message.chat.id] == 1) or message.chat.type == 'private':
                # Отправляем распознанный текст 
                if text.strip() != '':
                    bot.reply_to(message, text, reply_markup=get_keyboard('hide'))
                    my_log.log_echo(message, f'[ASR] {text}')
                else:
                    bot.reply_to(message, 'Очень интересно, но ничего не понятно.', reply_markup=get_keyboard('hide'))
                    my_log.log_echo(message, '[ASR] no results')
            # и при любом раскладе отправляем текст в обработчик текстовых сообщений, возможно бот отреагирует на него если там есть кодовые слова
            if text:
                message.text = text
                echo_all(message)
    
    
    
    def set_default_commands():
        """
        Reads a file containing a list of commands and their descriptions,
        and sets the default commands for the bot.
        """
        commands = []
        with open('commands.txt', encoding='utf-8') as file:
            for line in file:
                try:
                    command, description = line[1:].strip().split(' - ', 1)
                    if command and description:
                        commands.append(telebot.types.BotCommand(command, description))
                except Exception as error:
                    print(error)
        bot.set_my_commands(commands)
    
    
    def main():
        """
        Runs the main function, which sets default commands and starts polling the bot.
        """
        set_default_commands()
        bot.polling()
    
    
    if __name__ == '__main__':
    
        main()
  • Почему медленный wi fi на ПК?

    @theurus
    подними комп повыше Ж) сигнал может испортить даже толстая крышка стола
  • Почему requests не возвращает информацию которую я вижу в браузере?

    @theurus
    надо с тем же юзер агентом обращаться, а может и с тем же адресом и куками
  • Существуют ли аналоги Яндекс/Гугл фото в своей сети?

    @theurus
    +1 за syncthing. если надо запереть в локалке то на клиентах просто указываешь прямой локальный адрес до пира, так что бы телефон и компьютер только друг друга видели и только в локальной сети

    у меня с не очень большим количеством фоток (и других файлов - музыка итп) работает нормально
  • Почему низкая скорость маршрутизации на микротике?

    @theurus
    проверь на микротике что у сетей в бриджах MTU=1500, поставь принудительно
    разные сети должны быть в разных бриджах Ж)