Ответы пользователя по тегу Telegram
  • Как в Telethon обработать список с entities при пересылке группы сообщений?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    Решил проблему под свои нужды изменением кода в библиотеке. Оказалось, если передаётся список медиа, то он обрабатывается в этом блоке через цикл, с помощью вызова метода _send_album(), который даже не принимает переданные ранее formatting_entities .

    Поэтому, я дописал в аргументы метода _send_album() аргумент formatting_entities:
    async def _send_album(self: 'TelegramClient', entity, files, caption='',
                              formatting_entities=None,
                              progress_callback=None, reply_to=None,
                              parse_mode=(), silent=None, schedule=None,
                              supports_streaming=None, clear_draft=None,
                              force_document=False, background=None, ttl=None):

    И в сам вызов _send_album() тоже дописал передачу наших formatted_entities
    result = []
                while file:
                    result += await self._send_album(
                        entity, file[:10], caption=captions[:10], formatting_entities=formatting_entities,
                        progress_callback=used_callback, reply_to=reply_to,
                        parse_mode=parse_mode, silent=silent, schedule=schedule,
                        supports_streaming=supports_streaming, clear_draft=clear_draft,
                        force_document=force_document, background=background,
                    )
                    file = file[10:]
                    captions = captions[10:]
                    sent_count += 10
    
                return result

    Затем, внутри метода _send_album() после обработки подписей вставил код, чтобы formatted_entities к первому сообщению, если оно содержит текст:
    if captions and captions[0]:
                captions[0] = (captions[0][0], formatting_entities)

    Ну и всё заработало. Теперь группа отправляется с форматированием. Но эти изменения тоже необходимо немного подкорректировать чтобы они универсально работали в разных случаях.
    Ответ написан
  • Почему зависает авторизация Telethon на двухфакторной аутентификации?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    Основная проблема в файле библиотеки /telethon/client/auth.py в строке 23 - библиотека и метод getpass.getpass() не работает в консоли PyCharm в которой запускается бот, на этом месте программа и зависает.

    Возможное решение проблемы - изменить 23 строку:
    password: typing.Union[typing.Callable[[], str], str] = lambda: getpass.getpass('Please enter your password: '),
    на
    password: typing.Union[typing.Callable[[], str], str] = lambda: input('Please enter your password: '),

    * после переустановки или обновления Telethon нужно будет делать это повторно

    Вторая проблема - если явно передать строку с паролем в метод start(), то он должен работать, НО при проверке кода, внутри того же файла, атрибут password почему-то всеравно остаётся lambda-функцией. Позже попробую найти почему так и как это исправить.
    Ответ написан
    Комментировать
  • При отправки медиагруппы (несколько фото + текст) бот предложки отправляет каждое фото(видео) отдельно. А мне нужно, чтобы вместе) как исправить то?

    Это известная тема. Чтобы отправить медиагруппу, нужно контролировать её начало и конец. Но бот так же ловит каждое сообщение отдельным обновлением, у них разные id. Из общего - mediagrouop_id. Поэтому и отправляются они не группой, а каждое после получения обновления.

    Чтобы собрать группу, нужна либо машина состояний, либо функция для парсинга последних сообщений и проверки у них того же значения mediagroup_id. Но в Telegram Bot API по-моему нет возможности смотреть историю, только работать с обновлениями. Так что задача усложняется работой на лету.

    Как ещё одна альтернатива — использовать какой-нибудь Pyrogram на MTProto, в нём есть метод copy_mediagroup. Но конкретно эта библиотека давно не обновляется, будут проблемы с типизацией. Аналог — Telethon, но я ей не пользуюсь, не знаю есть ли там нужные инструменты.
    Ответ написан
    Комментировать
  • Как правильно посчитать длину текста с эмодзи в Python?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    Готовый редактор постов канала, некорректно работает только если есть группа медиа и описание написано не к первому медиа)) В таком случае ссылки добавятся к первому медиа, но в следующем тоже будет описание, в итоге Телеграм не покажет ни одно. Но это исключение, лень фиксить.

    from aiogram import Router, types, F
    from aiogram.utils import formatting as fmt
    
    
    # Редактор постов канала в отдельном роутере
    router = Router()
    
    # Это понадобится, чтобы в медиагруппе редактировалось только описание первого медиа
    check_mg = set()
    
    #Фильтры: проверим что пост не переслан и что это медиа имеющие caption
    @router.channel_post(~F.forward_from_chat, ~F.forward_from, (F.text | F.photo | F.video | F.animation | F.document))
    async def redactor(message: types.Message):
        # Собираем текстовые данные из поста
        text = message.text or message.caption or ''
    
        # Собираем те entities которые уже есть в посте
        ent = message.entities or message.caption_entities or []
    
        # Удаляем встроенные ссылки если они есть
        ent = [e for e in ent if e.type != 'text_link']
    
       # Через инструмент formatting создаём внешний вид будущего поста
        content = fmt.Text(
            # Старый текст
            text,
            '\n\n',
            # В моём случае я добавляю три ссылки на канал, чат и админа с эмодзи-разделителем
            fmt.as_line(
                fmt.Bold(fmt.TextLink("Канал", url='https://t.me/1')),
                fmt.Bold(fmt.TextLink("Чат", url='https://t.me/2')),
                fmt.Bold(fmt.TextLink("Админ", url='https://t.me/3')),
                # Тут эмодзи который будет между ссылками
                sep='  '
            )
        )
        # Собираем новый текст и новые entities в кучу
        text, new_ent = content.render()
    
        # Тут расписывать не буду, разные проверки и разные варианты отправки отредактированного сообщения
        if message.text is not None:
            if len(text) <= 4096:
                await message.edit_text(text, entities=ent + new_ent, disable_web_page_preview=True)
            else:
                print("Can't edit Text, length exceeded.")
        elif message.media_group_id is None:
            if len(text) <= 1024:
                await message.edit_caption(caption=text, caption_entities=ent + new_ent, disable_web_page_preview=True)
            else:
                print("Can't edit Caption, length exceeded.")
        elif message.media_group_id not in check_mg:
            check_mg.add(message.media_group_id)
            if len(text) <= 1024:
                await message.edit_caption(caption=text, caption_entities=ent + new_ent, disable_web_page_preview=True)
                await asyncio.sleep(1)
                check_mg.remove(message.media_group_id)
            else:
                print("Can't edit Caption, length exceeded.")
    Ответ написан
    Комментировать
  • Как избавиться от хлама после ботов?

    ПКМ по сообщению -> Удалить -> Удалить всё от <тут будет имя бота>
    Повторить для каждого бота
    Ответ написан
  • Aiogram: почему в Telegram не визуализируется voice сообщение?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    Из документации:
    For this to work, your audio must be in an .OGG file encoded with OPUS

    То есть, чтобы войс визуализировался, нужно отправлять его в формате .OGG, тогда и продолжительность будет отображаться корректно. А чтобы отображалась продолжительность (duration) при отправке других форматов, нужно явно её указать при отправке.

    Важное дополнение для Windows:
    1. Скачайте ffmpeg и распакуйте
    2. Добавьте путь в Path
    3. Функция на Python:
    import subprocess
    import io
    
    def mp3_to_ogg(filename, path=''):
        with open(f'{path}{filename}.mp3', 'rb') as input_file, open(f'{path}{filename}.ogg', 'wb') as output_file:
            mp3_io = io.BytesIO(input_file.read())
            ffmpeg_command = ['ffmpeg', '-i', 'pipe:0', '-c:a', 'libopus', '-f', 'ogg', 'pipe:1']
            result = subprocess.run(ffmpeg_command, input=mp3_io.read(), capture_output=True)
            ogg_bytes = result.stdout
            output_file.write(ogg_bytes)

    *вы можете изменить функцию, например добавив путь к файлам, использовав временные файлы и т.д.
    Ответ написан
    1 комментарий
  • Есть ли возможность получить ID юзеров, поставивших реакции в чате Telegram, с реализацией на Python?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    https://qna.habr.com/q/1249668 ответ с реализацией с помощью библиотеки Pyrogram
    Ответ написан
    Комментировать
  • Как сделать уведомление в Aiogram?

    https://docs.aiogram.dev/en/latest/telegram/types/...
    await bot.answer_callback_query(callback_query_id=cmd.id, text="Уведомление", show_alert=True)

    либо
    await callback_query.answer("Уведомление", show_alert=True)
    Ответ написан
    4 комментария
  • Как сделать бот в Телеграм без приставки bot на конце?

    1. Авторизоваться с аккаунта, который будет использоваться в качестве бота тут: https://my.telegram.org/

    2. Создать там "приложение" и получить API id, API hash.

    3. Написать бота на библиотеке, поддерживающей Telegram client API, например Pyrogram
    (я пользуюсь им) https://docs.pyrogram.org/ или Telethon https://docs.telethon.dev/en/stable/ .
    Ответ написан
    2 комментария
  • Как посмотреть ID старых сообщений на телеграмм канале?

    Можно спарсить историю чата и собрать из неё нужную информацию, если нужен айди старого сообщения. Делал это на библиотеках Telethon и Pyrogram. НО учти, что для этого нужен уже не бот, а юзер (юзербот). Так же эти варианты подойдут и для автопостинга с других каналов через "хендлер".

    Мне больше понравилась реализация на Pyrogram. И там очень хорошая понятная документация, есть примеры.
    Ответ написан
    Комментировать
  • Ошибка в боте, который отправляет комментарии.Что делать?

    Во первых не светите свой ID и Hash на форумах, это как логин и пароль от аккаунта)

    Ошибка у вас из-за того, что в цикле переменная msg это и есть сообщение чата. Нужно сделать так:
    print(f”Пропускаем уже обработанное message _id={msg.id}”)


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

    Возможно вы имеете в виду Чат? Если да, то схема такая:
    1. Создаём бота
    2. Добавляем в чат
    Работа кода:
    3. Ловим служебное сообщение о новом пользователе
    4. Выполняем необходимые действия.

    Это всё работает внутри чата, тк:
    1. Служебные сообщения присутствуют только в чате.
    2. Бот не может писать пользователю в личные сообщения первым. Только отвечать в чате.

    Код зависит от библиотеки.
    Ответ написан
    Комментировать
  • Pyrogram bot: как отправить фото по айди?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    Всем большое спасибо за подсказки, особенно User . Проблема была как раз в фильтре. Нужно было искать photo и photo.file_id.
    Универсальный вариант - скачивать и отправлять фото, т.к. пересылка не будет работать из закрытых чатов. Вот такую функцию по-быстрому сообразил для загрузки фото.
    async def dl_last_photo(target):    #передаём в функцию ID или Username чата
        async for msg in app.get_chat_history(target, limit = 50, offset_id = -1):    #ищем в истории с конца, обрабатываем 50 сообщений
            if msg.photo:    #если есть фото
                print(msg.photo.file_id)    #в консоль выводим ID - не обязательно
                await app.download_media(msg.photo) #скачиваем фото из сообщения в стандартный каталог (папка_бота/downloads)


    По аналогии можно фильтровать и другие типы файлов. Так же можно менять папку, куда скачивается файл. И если вы уверены, что чат открыт и разрешена пересылка - можно и сразу переслать фото по ID куда нужно.
    Ответ написан
    Комментировать
  • Пишу тг бота для отправки комментариев на pyrogram. Выдаёт ошибку,что делать?

    В такой каше сложно разобраться. Но если я правильно понимаю, ты пытаешься проверить несуществующий атрибут:
    Выдаёт ошибку: if (msg.from_user is None and msg.forward_from_chat.id == public.id):
    AttributeError: ‘NoneType’ object has no attribute ‘I’d’

    Из твоего кода:
    if (msg.from_user is None) # если сообщение не имеет автора
    # и это репост из паблика (проверка по id)


    Это так не работает. Если нет автора, то такого атрибута нет вообще, эта часть не работает. Вот тебе пример на Pyrogram как из сообщения вытащить ID.
    any_sender_id = message.from_user.id if message.from_user else message.sender_chat.id #вытаскиваем ID
    if any_sender_id == public.id: #проверяем что это нужный паблик
        #дальше твоя логика

    Если сообщение "from_user", значит принимает его ID. Иначе - принимает ID чата/канала.

    этот же код чуть понятнее:
    any_sender_id = None    #объявляем переменную для хранения ID
    if message.from_user:    #если у нас есть параметр from_user
        any_sender_id = message.from_user.id    #присваеваем ID юзера
    else:    #иначе
        any_sender_id = message.sender_chat.id    #присваеваем ID канала или чата
    
    if any_sender_id == public.id:    #проверяем что это нужный паблик
        #дальше твоя логика
    Ответ написан
    Комментировать
  • Как найти бота или чат по id в Telegram?

    Смотря какой библиотекой будешь пользоваться.
    Ответ написан
  • Telegram userbot на Telethon не редактирует пересланные сообщения. Как исправить?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    Проблема решена! Само собой как-то заработало, в коде ничего не менял.

    Возможно, это какой-то глюк с сессиями, если ты в ТГ с этого же аккаунта в данный момент. Хотя в консоли никаких ошибок небыло, когда тестировал.

    Сейчас функция работает и с текстом, и с пересланными сообщениями. Иногда долговато - несколько секунд (бота залил на Heroku).
    Ответ написан
  • Aiogram: как обработать только одно "сообщение" из message.content_group?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    ec4b39bd9159b4972c016d7384e84ee0.jpg
    Решение проблемы из разряда "зато работает":
    # к тому что есть добавил это
    from time import sleep
    # список, где будет храниться message.media_group_id
    check_mess = []
    
    @dp.channel_post_handler(content_types=['any'])
    async def auto_redactor(message: types.Message):
        
        text = message.text
        if isinstance(message.caption, str):
            caption = message.caption
        else:
            caption = ''
    
        if hasattr(message, 'text') and isinstance(text, str):
            await message.edit_text(f'{text}\n\nподпись к тексту',parse_mode="HTML")
    # добавил проверку, что media_group_id ещё не в списке
        elif hasattr(message, 'caption') and message.media_group_id not in check_mess:
    # добавляем в список наш media_group_id
            check_mess.append(message.media_group_id)
            await message.edit_caption(f'подпись к медиа',parse_mode="HTML")
    # чищу список после 5 сек ожидания, чтобы хендлер успел обработать все медиа
            sleep(5)
            check_mess.clear()
    Ответ написан
    Комментировать
  • Aiogram: Нет InlineKeyboardButton под постами с несколькими фото. В чём проблема?

    EntireMusic
    @EntireMusic Автор вопроса
    (:
    В общем, я сдался.
    Сегодня протестировал ручную отправку медиагруппы и оказалось, что для bot.send_media_group просто-напросто нет аргумента reply_markup, как и на уровне прикрепления фото. Поэтому, без костылей уж точно не получится написать код, где к группе медиа прикрепляется InlineKeyboardButton. А может и вовсе нет такой возможности.
    Ответ написан
    Комментировать