Хабрахабр

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

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

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

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

Я знаком с Pascal, FoxPro, Interbase и даже (ха-ха 3 раза) 20 лет назад продавал свои программы, а потом как-то не сложилось, ушел в торговлю. Прочитал первый попавшийся в инете самоучитель на 149 страниц. Но вернемся к 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 = 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 заблокирован, для разработки бота локально нужно как-то пропустить трафик через наших доблестных защитников. Пара слов о том, как пришлось воевать с роскомнадзором. Самым простым и быстрым и “нормальным” способом можно считать ssh тоннель: устанавливаем соединение между клиентом и proxy сервером, получаем на локальном хосте порт куда можно посылать трафик с нашей стороны, а выйдет он с другой стороны (уже где-то в Германии). Сделать это можно двумя путями — через VPN или через 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

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

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

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

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

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

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть