Современное программирование: взгляд после 25 лет перерыва или как я писал бота для Телеграм

Задача кажется простой, когда ничего про нее не знаешь и когда решил.

В один “прекрасный” день, я понял, что мне не интересно сидеть на многочисленных форумах, а хочется создать свой канал и делиться “мудростью”.

Мне нравится Телеграм заложенными в него возможностями в том числе и ботами, поэтому канал в виде блога был создан там. Начал искать ботов, помогающих оформлять сообщения…. а так как мне хочется не нашел. Что ж, напишем сами. Умные люди посоветовали писать на Python.

Прочитал первый попавшийся в инете самоучитель на 149 страниц. Я знаком с Pascal, FoxPro, Interbase и даже (ха-ха 3 раза) 20 лет назад продавал свои программы, а потом как-то не сложилось, ушел в торговлю. Работа программистом мне сильно помогла в постановке задач для кодеров кстати. Но вернемся к Python, кажется, ничего сложного, ведь и на BASIC программировать можно было и это не мой институтский диплом с программно-аппаратным комплексом генератора поверки МИГа на Assembler. Одна проблема, всё это было давно, так что возвращаясь к заголовку — кажется что просто, потому что пока ничего не знаю про задачу, но попробовать стоит.

Я решил, что удобнее всего делать проект со смартфона на Андроид, ибо он всегда под рукой. Итак ставим:

  1. Pydroid 3 — IDE for Python 3 Собственно Питон для Андроид.
  2. @BotFather, В Телеграм устанавливаем отца всех ботов — он понадобится чтобы получить идентификатор вашего бота и сделать основные настройки.
  3. Rebootr Приложение для запуска проекта на heroku.
  4. GIT Приложение для онлайн-хостинга репозиториев.
  5. Windscribe Без VPN никуда?
  6. Termux Эмулятор терминала и среды Linux.

И что в сухом остатке? Программировать на смартфоне можно в теории, но невозможно на практике. Максимум проверить код, исправить ошибку, исследовать работоспособность.

Такое длинное вступление, а что я хотел получить от своего бота. Сначала мне показалось достаточным добавлять в конце сообщения Хэштег. Потом пришла мысль “накрыть” его ссылкой на мой канал, так при репосте будет дополнительная завлекуха на канал источник. Потом, добавил автоматизацию ссылки на источник, откуда я беру сообщение. Далее сделаю лирическое отступление. Реклама, конечно двигатель прогресса. Но иногда ее количество зашкаливает. Телеграм был выбран мной в том числе и из-за того, что тут есть возможность бороться с последней. Я уважаю читателей своего канала и поэтому интересные новости, найденные на просторах инета чищу от рекламы и отправляю в канал. В то же время я уважаю авторов и практически всегда даю ссылку на источник в виде “Читать далее...”. По причине нелюбви рекламы я скачиваю контент с Ютуба и выкладываю его в своем канале в виде видеофайла. В один определенный момент бот, который качал видео сошел с ума и стал присылать мне рекламу каждый час. Так в моем боте появилась возможность скачивать видео с ютуба. Недавно кстати познакомился с автором этого бота, он был сильно удивлен, т.к. по его словам отправляет рекламу “всего” 20 раз в месяц. Тоже самое произошло и с ботом, который делает водяной знак — он был отправлен в топку, а у меня появилась возможность делать водяной знак.

Для того, чтобы практически с нуля написать программу пришлось много информации искать в интернете. Надеюсь, что тем, кто пойдет по моим стопам это поможет. Итак откуда я черпал информацию и чем пользовался:

  1. Мне действительно помогли статьи на Хабре. Поэтому не буду переписывать как и что установить. Тут все есть. Кстати, я обращался в личку к авторам и мне ни разу не отказали в помощи.
  2. github Сервис онлайн-хостинга репозиториев, обладающий всеми функциями распределенного контроля версий и функциональностью управления исходным кодом. Букварь
  3. heroku — облачная PaaS-платформа, поддерживающая ряд языков программирования. Очень быстро от него отказался.
  4. pyTelegramBotAPI — Одна из основных библиотек при написании бота для Телеграм.
  5. Учебник по написанию ботов
  6. Python 3 для начинающих
  7. Боты: информация для разработчиков
  8. Справочник по HTML
  9. Без VPN никуда?

Второе лирическое отступление или война план покажет. Когда я начал писать бота, первым делом посмотрел чужие коды. Если нет каментов понять можно с трудом:

Земля тряслась — как наши груди,
Смешались в кучу кони, люди,
И залпы тысячи орудий
Слились в протяжный вой…

Лермонтов писал о коде. В куче лежат функции, декораторы. Нет красоты кода, о ресурсах никто не заботится. Хотя красоту скорее всего может увидеть извращенец мазохист. До меня очень быстро дошел смысл фразы знакомого программиста “Посмотри прогу, может быть разберешься”. Самый главный взрыв мозга у меня был, когда я наконец то осознал, что код событийный, а не последовательный. Это другой уровень.

Вторая проблема отсутствие хорошей документации. Даже на басурманском. Приведу пример. Я отправляю в телеграм картинку, а он ее безбожно жмет. Оказалось что в строке был прописан неверный аргумент:

file_info = bot.get_file(message.photo[-1].file_id)

А что документация? Идем к первоисточнику

image

image

Это же массив. Можно по нему пройтись, поизучать, где какой размер возвращается. Спасибо, умные люди подсказали, что прописать. Хотя о чем я, если даже гуру в недоумении.

Когда писал код водяного знака использовал бесплатный шрифт и чтобы сделать его жирным применил решение вывода сообщения трижды со смещением на пиксель, не знаю насколько красивое решение, но работает.

font = ImageFont.truetype("Pillow/Tests/fonts/FreeMono.ttf", width//20)
pos = (width//4, height - height//10)
text = skanal
drawing.text(pos, text, fill=black, font=font)
pos = (1 + width // 4, 1 + height - height // 10)
drawing.text(pos, text, fill=black, font=font)
pos = (2 + width // 4, 2 + height - height // 10)
drawing.text(pos, text, fill=black, font=font)

Позиция как видите выбирается в зависимости от размера картинки, высота шрифта тоже. Тут же столкнулся с интересным моментом: хотя шрифт и является неотъемлемой частью библиотеки PIL, так как в первой строке написано локально работает, а в Docker — нет. Выход скачать его в репозиторий, добавить путь в файл окружения и прописать другой путь в проге.

Еще один непостижимый для меня момент произошел с картинкой после обработки с помощью библиотеки PIL (сразу после водяного знака). Отправляю ее в свой бот:

 with open(photo_path, 'rb') as fi:
    bot.send_photo(message.chat.id, fi)

Все замечательно, картинка нравится. Затем мне требуется добавить к картинке комментарий и посмотреть, а красиво ли все смотрится вместе? Пишем:

bot.send_photo(message.chat.id, message.photo[-1].file_id, caption='Какая красота')

В бот почему то уходит первоначальная, необработанная картинка. Хорошо, попробуем обмануть: getupdates.offset -1 толку никакого, Телеграм уверен, что это одно и тоже фото. Хорошо, делаем так:

 with open(photo_path, 'rb') as fi:
    info = bot.send_photo(message.chat.id, fi)

Переписываем:

bot.send_photo(message.chat.id, info.photo[-1].file_id, caption='Какая красота')

Результат тот же — выводится первоначальная картинка. И только замена message в первом аргументе на info дала желаемый результат.

Также тут приведу кусок интересного кода начального уровня загрузки с ютуб (NB: без проверки на ошибки):

elif message.entities:             # Работа со ссылками pkanal = 6
        for item in message.entities:
           if item.type == "url" and message.text.find('  ') == -1:
               if 'youtube.com' in message.text or 'youtu.be' in message.text:           #  Загружаем с Ютуб
                   ydl_opts = {'outtmpl': '/tmp/f.mp3', 'preferredcodec': 'mp3', 'max_filesize': 60000000}
                   link_of_the_video = message.text
                   with youtube_dl.YoutubeDL(ydl_opts) as ydl:
                       ydl.download([link_of_the_video])
                   bot.delete_message(message.chat.id, message.message_id)

                   if os.path.exists('/tmp/f.mp3'):  # файл есть
                       video = open('/tmp/f.mp3', 'rb')
                       bot.send_video(message.chat.id, video)
                       os.remove('/tmp/f.mp3')
                       pkanal = 6
                   else:       # файла нет
                       bot.send_message(message.chat.id, 'Слишком большой файл', parse_mode='html', disable_web_page_preview=True)

Для меня было камнем преткновения, что entities это массив массивов и надо “пробежаться” по всему массиву чтобы бот понял, что работаем со ссылкой. Еще выяснилось, что пользователи отправляют ссылку в бот как “Поделиться” из Ютуб поэтому в примере прописано еще и “youtu.be”. Как сразу отправить в Телеграм файл я не придумал, поэтому мы его сохраняем, отправляем и затем удаляем. Во время тестирования мне сразу указали на то, что люди начнут качать гигантские файлы — позднее пришлось ввести ограничение.

Перед релизом бота вдруг выяснилось, что у меня нет проверки на права доступа в канал. К примеру зная мой канал любой пользователь бота мог туда отправить сообщение, т.к. бот является Администратором. Пришлось срочно делать проверку:

if message.from_user.id in [adm_obj.user.id for adm_obj in bot.get_chat_administrators(chat_id)]:

Тут получаем от канала список Администраторов и смотрим является ли автор сообщения тоже Администратором.

Пара слов о том, как пришлось воевать с роскомнадзором. Поскольку доступ к API заблокирован, для разработки бота локально нужно как-то пропустить трафик через наших доблестных защитников. Сделать это можно двумя путями — через VPN или через proxy. Самым простым и быстрым и “нормальным” способом можно считать ssh тоннель: устанавливаем соединение между клиентом и proxy сервером, получаем на локальном хосте порт куда можно посылать трафик с нашей стороны, а выйдет он с другой стороны (уже где-то в Германии). Для удобства можно добавить некое подобие автоматизации этого соединения — скрипт и ярлык на рабочем столе, которым его запустим, при необходимости. Под “нормальным” способом здесь я понимаю ситуацию, где входную и выходную точку контролируем мы сами — слева наш ноутбук, справа VPS в Германии. по середине трафик могут перехватывать сколько угодно, он шифрованный, а на выходе мы оказываемся в юрисдикции другого государства, и законы РФ к нему не применимы. Как плюс мы получаем дополнительно гарантию того что proxy сервер не будет изменен или выключен, пока мы не сделаем этого самостоятельно. Т.е. в отличие от всяких дядиных VPN у нас появляется спокойствие и уверенность в завтрашнем дне.

Скрипт

/home/user/proxy.sh

Код скрипта

#!/bin/bash
ssh -f -D 1080 user@12.34.56.78 sleep 72000

После того как у нас соединение с сервером установлено, а порт открыт, нам нужно как-то направить туда трафик. Идя по пути наименьшего сопротивления и чтобы не думать о том как настраивать proxy в IDE\docker\python можно сделать одну настройку на всех, такой настройкой будет выступать proxychains. Если запустить любой софт с помощью этой утилиты, то она перенаправит трафик через цепочку proxy которые прописаны в конфиге.

/etc/proxychains.conf

В нашем случае это одна цепочка и написать ее не составляет никакого труда.

socks5 127.0.0.1 1080

и еще один костыль, который был предпринят, чтобы только не настраивать VPN (сарказм) — это способ запуска питоновского приложения из PyCharm. В простом случае чтобы запустить через proxychains приложение достаточно написать proxychains app.py и всё. Но в IDE обязательно требуется указать интерпретатор. Обойти это просто — создаем новую «run configuration», выбираем shell script. и заполняем поля

image

После чего запуск с точки зрения IDE приобретает такой вид: proxychains python3 app.py — собственно это нам и надо. Таким образом, когда мы хотим заняться проектом все что нужно сделать — запустить скрипт на рабочем столе, а потом для запуска бота нажать кнопку “play" в ide. Всю остальную магию сделают proxychains и ssh.

Наконец бот написан, оттестирован. Что дальше? С одной стороны хочется заявить о себе, с другой стороны, я думаю, он реально может кому-то пригодиться. И тут мы сталкиваемся с еще одной проблемой Телеграм; у него нет единого каталога каналов и ботов. Вполне возможно бот подобный моему существует, но повторюсь я его не нашел. А где-то в трамвае сидит и мучается человек, которому хочется красиво оформить сообщение в канал и он все делает ручками.

Если вы уже запустили мой бот, то увидели, что есть хэштег #Реклама. Как же так? — спросите вы. А тут я пошел на поводу у конечных пользователей — многие выкладывают рекламу в своих каналах и быстро привыкнув к оформлению сообщений с помощью бота, попросили добавить. Рекламу можно не любить, бороться с ней, но это суровые и необходимые для пользователей реалии.

Проект некоммерческий, поэтому думаю можно назвать сам бот @SGK_espace_bot.

А тут видео как пользоваться
Буду благодарен за любую конструктивную критику.

Similar posts

Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 39

    0
    Я написал github.com/pawnhearts/lctelegate полностью на смартфоне. Тестил запуская по ssh.
      0

      Я не смог. При зрении -3 не ношу очки.

      +4

      Могу предложить другую схему?
      Выкинуть все, что Вы использовали.
      Оставить:


      1. Сервер на digitalocean — будем на него деплоить scp, там будет крутиться наш бот. Можно взять не DO, а heroku или любое другое аналогичное решение.
      2. Gitlab — в нем мы можем хранить код (безлимитное количество приватных репозиториев). Также гитлаб поможет нам собирать код и деплоить его на сервер из п.1.

      Разработку можно вести прямо в WebIDE гитлаба. Она поддерживает подсветку синтаксиса python. И вряд ли интерфейс WebIDE гитлаба будет сильно хуже редактора прямо на самом смартфоне.

        +2

        Когда использовал heroku, я даже с компа иной раз правил код сразу в GitHub.

          +3

          Сейчас деплой происходит так: локально билдится контейнер и выкатывается на docker hub, затем с помощью ansible прогоняется плейбук по виртуалке в hetzner. Он пуллит с докерхаба образ и сравнивает с текущим, если есть изменения то перезапускает systemd unit сервис, который перезапускает докер контейнер с ботом. Планируется еще сделать чтобы по пушу в гитхаб сборка контейнера и выкатка в докерхаб была автоматом, с наскока не разобрался. Github вполне не хуже gitlab, а потому абсолютно нет смысла менять инструмент.

            0

            Полностью солидарен с тем, что "Github вполне не хуже gitlab". Но тут нюанс, что пока еще github не полностью self-contained решение. В случае гитлаба — там же можно хранить образы докеров, не заливая их на докер-хаб, к тому же докер-хаб для более 1 приватного регистри — платен. Можете сами решить насколько это приемлемо, я не навязываю какой-либо конкретный продукт.


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

            ну, либо настраивать интеграцию со стороны докерхаба, либо можно воспользоваться github actions. Варианты ± равноценные.

              +1
              В связи с последними событиями в gitlab, его использовать вообще не очень приятно.
              Для данной задачи кмк вообще инструмент хранения кода не особо важен, поэтому нет смысла особо зацикливаться гитлаб или гитхаб. Ну и смущает вендор лок — завязываться на том что вендор дает все что вы описали сегодня бесплатно может вылиться в то что завтра придется с горящей жопой искать новый набор решений, потому что в любой момент гитлаб может изменить условия игры.
                0

                Это относится к любому SaaS сервису. Я уже говорил, что DockerHub бесплатен только для одного приватного регистри, а завтра они точно так же могут изменить правила игры (тем более, что над Docker Inc. сгущаются тучи в связи с https://habr.com/ru/company/flant/blog/475814/ )


                Ну и смущает вендор лок

                вендор-лок в случае гитлаба весьма условный. Место хранения кода — легко поменять (на bitbucket, github, anything else). Сборщик кода (CI) — можно легко поменять на circle-ci, travis, jenkins etc. Хранение образов — тоже легко перекатиться на любой registry. И т.д. Вопрос именно в трудоемкости переноса — она есть, она не ничтожна, она ощутима, но не беспредельна. И это не из серии перехода с 1С на SAP.

          +8

          "Как я писал бота" вижу. Взгляда на современное программирование спустя 25 лет перерыва не вижу, а было бы интересно. Или этот взгляд описывается терниями с vpn/proxy и ркн?

            –1
            Нет красоты кода, о ресурсах никто не заботится. Хотя красоту скорее всего может увидеть извращенец мазохист. До меня очень быстро дошел смысл фразы знакомого программиста “Посмотри прогу, может быть разберешься”. Самый главный взрыв мозга у меня был, когда я наконец то осознал, что код событийный, а не последовательный. Это другой уровень.
            Вторая проблема отсутствие хорошей документации. Даже на басурманском.
            Непредсказуемый результат как в примере с message.chat.id.

            Решил дописать. Вот есть задумка добавить водяной знак на видео. Как найти библиотеку которая поможет? Или какая библиотека работает с html? И просто риторический вопрос — почему тот же Дуров не предусмотрел единой базы каналов и ботов?
              +2
              Нет красоты кода, о ресурсах никто не заботится.

              Это вы посмотрели код каких-то ботов, и на основании этого делаете выводы о современном программировании?


              Вторая проблема отсутствие хорошей документации.

              Хорошей документации на что?


              Вот есть задумка добавить водяной знак на видео. Как найти библиотеку которая поможет?

              video watermarking in python


              Или какая библиотека работает с html?

              html processing in python

                –1

                Вторая проблема отсутствие хорошей документации.
                <<Хорошей документации на что?>>
                Извините, а примеров в статье недостаточно?

                  +5

                  Нет. Потому что, насколько я могу понять по вашему тексту, подавляющая часть ваших претензий — к апи телеграма и/или какой-то реализующей его библиотеке.

                    –1

                    С чем столкнулся о том и написал. И слово то какое нехорошее "претензии".

                      +2
                      И слово то какое нехорошее "претензии".

                      Такое же, как "проблема".


                      С чем столкнулся о том и написал.

                      Ну то есть вы столкнулись с проблемой в какой-то конкретной области, а пишете о "современном программировании"?

                        0
                        • Если бы все так было просто, то не существовало бы два разных слова.
                        • Предложите другое, более полное название статьи. ИМХО в названии есть все "необходимые и достаточные условия"
                          +2
                          Если бы все так было просто, то не существовало бы два разных слова.

                          Так я и не говорю, что это одинаковые слова, я говорю, что одно из них не более "нехорошее", чем другое.


                          Предложите другое, более полное название статьи.

                          О, это очень просто. "Как я писал бота для Телеграм после 25 лет перерыва в программировании".

                            –3

                            Иезуиты аплодируют. Надо понимать что в название уже заложено отношение (видение) автора к проблеме.

                              +4

                              Ну так об этом и речь: что проблема в заголовке озвучена одна, а в посте написано совсем другое.

                                –3

                                ИМХО это спор стакан наполовину пуст или полон.

                    0

                    Эджайл манифест.


                    Хороший продукт — важнее хорошей документации.
                    Это не означает, что последней не должно быть в принципе, но в условиях сжатого TTM документация без продукта нафиг никому не нужна. Поэтому имеем, что имеем

                    0

                    Вот есть задумка добавить водяной знак на видео. Как найти библиотеку которая поможет?
                    video watermarking in python
                    Или какая библиотека работает с html?
                    html processing in python


                    Спасибо.

                +7

                Очень сомнительным решением выглядит загрузка видео с YouTube, очистка его от рекламы и выкладывание на свой канал. Да ещё и со своими водяными знаками. Во-первых, права на такое действие автор видео явно не передавал (если в подписи к видео не указано иное… Ну или если нет прямой договоренности с автором). Во-вторых, на создание видео были потрачены усилия, время и, вполне вероятно, деньги. Так что автор имеет полное право поставить рекламу в видео, чтобы хотя бы попытаться выйти в ноль (а может и в плюс) по затратам. Это не неуважение к пользователю, это просто желание получить условно-справедливую оплату за свою работу. А лишать авторов контента этого — ну, такое себе… Кто-то из-за этого (снижение заработков) может просто перестать записывать и выкладывать интересные ролики.

                  –3
                  1. Пока в боте не реализована возможность делать водяной знак на видео. Хотя думаю сделать, т.к. часто вижу свои ролики без ссылок на источник. :-)
                  2. Рассмотрим ситуацию:… имея дома нож я что потенциальный Чикотила? Передав кому то нож — я тоже являюсь пособником преступления? Нет — а уж хлеб им режут или кого то, я не могу нести ответственности.
                  +2
                  Тут же столкнулся с интересным моментом: хотя шрифт и является неотъемлемой частью библиотеки PIL, так как в первой строке написано локально работает, а в Docker — нет.
                  ImageFont.truetype("Pillow/Tests/fonts/FreeMono.ttf", width//20)

                  Вы, я так понимаю, с тем, где и как размещаются пакеты в python разбираться не стали? И слово Tests в пути вас тоже не смутило?

                    0

                    К сожалению не стал и не смутило. За месяц я переварил такой объем инфы, что иногда на ровном месте делал глупости. Я никогда не работал раньше с Линуксом, не знал даже слов Python, github, heroku, имел представление о прокси как банальный эрудит, а знакомство с VPN сводилось исключительно к использованию ТОР браузера.

                      +5

                      У меня, простите за прямоту, создается ощущение, что ваш "взгляд на современное программирование после 25 лет перерыва" сводится к "за месяц не разобрался". Ну да, это нормально. За месяц не разберешься.

                        0

                        постараюсь не снизить темпы

                    0
                    очень интересно
                      0

                      Спасибо, вдруг чем то поможет.

                      +2
                      pyTelegramBotAPI — Одна из основных библиотек при написании бота для Телеграм.


                      Ну зачем так-то?

                      Есть же aiogram:
                      • со своевременными обновлениями (день в день с релизами Teleram Bot API)
                      • с async, а не с воркерами на тредах
                      • с готовыми решениями (FSM, LeakyBucket и др.)
                      • с готовыми интеграциями (Redis, Mongo и др.)
                      • с русскоязычным сообществом


                      + В статье было бы уместно сослаться на перечень библиотек/фреймворков, опубликованный в документации Telegram:
                      core.telegram.org/bots/samples
                        –1

                        Да, надо переползать
                        https://docs.telethon.dev/en/latest/
                        https://aiogram.readthedocs.io/en/latest/search.html?q=download&check_keywords=yes&area=default
                        Пишу с мобилы — простите за стиль.

                          0
                          Наконец бот написан, оттестирован.

                          За первые пару минут пользования ботом наткнулся на пару весьма неприятных багов, которые убивают весь функционал Вашего бота:
                          • После первой отправки боту изображения — оно возвращается корректно. При последующих отправках возвращается всё та же картинка из первого сообщения
                          • При попытке загрузить видео с YouTube, независимо от ссылки, в ответ ты всегда получаешь Гену с Чебурашкой

                          image
                          image

                          А тут я пошел на поводу у конечных пользователей — многие выкладывают рекламу в своих каналах и быстро привыкнув к оформлению сообщений с помощью бота, попросили добавить


                          Не совсем ясно, какие такие пользователи привыкли к «оформлению сообщений с помощью бота», если обе его функции практически полностью нерабочие.
                            0

                            Я вчера его "сломал". Сегодня буду разбираться, что случилось. Приношу извинения. Проект не коммерческий. :-)

                              0
                              При попытке загрузить видео с YouTube, независимо от ссылки, в ответ ты всегда получаешь Гену с Чебурашкой

                              тонкий намёк на грядущий Чебурнет....
                                0

                                Исправил. Тестируйте. Не тот релиз выложил. Просто у меня будет еще водяной знак на видео и автоматическая подготовка статьи с новостных сайтов для публикации в канал

                                  0

                                  Добавил
                                  import moviepy
                                  from moviepy.editor import *
                                  и все порушилось. Думаю автоматически подгрузилась OS из moviepy

                                    +1
                                    Поэтому и рекомендуют избегать неявных импортов :)
                                      0

                                      Победил

                            Only users with full accounts can post comments. Log in, please.