В один “прекрасный” день, я понял, что мне не интересно сидеть на многочисленных форумах, а хочется создать свой канал и делиться “мудростью”.
Мне нравится Телеграм заложенными в него возможностями в том числе и ботами, поэтому канал в виде блога был создан там. Начал искать ботов, помогающих оформлять сообщения…. а так как мне хочется не нашел. Что ж, напишем сами. Умные люди посоветовали писать на Python.
Прочитал первый попавшийся в инете самоучитель на 149 страниц. Я знаком с Pascal, FoxPro, Interbase и даже (ха-ха 3 раза) 20 лет назад продавал свои программы, а потом как-то не сложилось, ушел в торговлю. Работа программистом мне сильно помогла в постановке задач для кодеров кстати. Но вернемся к Python, кажется, ничего сложного, ведь и на BASIC программировать можно было и это не мой институтский диплом с программно-аппаратным комплексом генератора поверки МИГа на Assembler. Одна проблема, всё это было давно, так что возвращаясь к заголовку — кажется что просто, потому что пока ничего не знаю про задачу, но попробовать стоит.
Я решил, что удобнее всего делать проект со смартфона на Андроид, ибо он всегда под рукой. Итак ставим:
- Pydroid 3 — IDE for Python 3 Собственно Питон для Андроид.
- @BotFather, В Телеграм устанавливаем отца всех ботов — он понадобится чтобы получить идентификатор вашего бота и сделать основные настройки.
- Rebootr Приложение для запуска проекта на heroku.
- GIT Приложение для онлайн-хостинга репозиториев.
- Windscribe Без VPN никуда?
- Termux Эмулятор терминала и среды Linux.
И что в сухом остатке? Программировать на смартфоне можно в теории, но невозможно на практике. Максимум проверить код, исправить ошибку, исследовать работоспособность.
Такое длинное вступление, а что я хотел получить от своего бота. Сначала мне показалось достаточным добавлять в конце сообщения Хэштег. Потом пришла мысль “накрыть” его ссылкой на мой канал, так при репосте будет дополнительная завлекуха на канал источник. Потом, добавил автоматизацию ссылки на источник, откуда я беру сообщение. Далее сделаю лирическое отступление. Реклама, конечно двигатель прогресса. Но иногда ее количество зашкаливает. Телеграм был выбран мной в том числе и из-за того, что тут есть возможность бороться с последней. Я уважаю читателей своего канала и поэтому интересные новости, найденные на просторах инета чищу от рекламы и отправляю в канал. В то же время я уважаю авторов и практически всегда даю ссылку на источник в виде “Читать далее...”. По причине нелюбви рекламы я скачиваю контент с Ютуба и выкладываю его в своем канале в виде видеофайла. В один определенный момент бот, который качал видео сошел с ума и стал присылать мне рекламу каждый час. Так в моем боте появилась возможность скачивать видео с ютуба. Недавно кстати познакомился с автором этого бота, он был сильно удивлен, т.к. по его словам отправляет рекламу “всего” 20 раз в месяц. Тоже самое произошло и с ботом, который делает водяной знак — он был отправлен в топку, а у меня появилась возможность делать водяной знак.
Для того, чтобы практически с нуля написать программу пришлось много информации искать в интернете. Надеюсь, что тем, кто пойдет по моим стопам это поможет. Итак откуда я черпал информацию и чем пользовался:
- Мне действительно помогли статьи на Хабре. Поэтому не буду переписывать как и что установить. Тут все есть. Кстати, я обращался в личку к авторам и мне ни разу не отказали в помощи.
- github Сервис онлайн-хостинга репозиториев, обладающий всеми функциями распределенного контроля версий и функциональностью управления исходным кодом. Букварь
- heroku — облачная PaaS-платформа, поддерживающая ряд языков программирования. Очень быстро от него отказался.
- pyTelegramBotAPI — Одна из основных библиотек при написании бота для Телеграм.
- Учебник по написанию ботов
- Python 3 для начинающих
- Боты: информация для разработчиков
- Справочник по HTML
- Без VPN никуда?
Второе лирическое отступление или война план покажет. Когда я начал писать бота, первым делом посмотрел чужие коды. Если нет каментов понять можно с трудом:
Земля тряслась — как наши груди,
Смешались в кучу кони, люди,
И залпы тысячи орудий
Слились в протяжный вой…
Лермонтов писал о коде. В куче лежат функции, декораторы. Нет красоты кода, о ресурсах никто не заботится. Хотя красоту скорее всего может увидеть извращенец мазохист. До меня очень быстро дошел смысл фразы знакомого программиста “Посмотри прогу, может быть разберешься”. Самый главный взрыв мозга у меня был, когда я наконец то осознал, что код событийный, а не последовательный. Это другой уровень.
Вторая проблема отсутствие хорошей документации. Даже на басурманском. Приведу пример. Я отправляю в телеграм картинку, а он ее безбожно жмет. Оказалось что в строке был прописан неверный аргумент:
file_info = bot.get_file(message.photo[-1].file_id)
А что документация? Идем к первоисточнику
Это же массив. Можно по нему пройтись, поизучать, где какой размер возвращается. Спасибо, умные люди подсказали, что прописать. Хотя о чем я, если даже гуру в недоумении.
Когда писал код водяного знака использовал бесплатный шрифт и чтобы сделать его жирным применил решение вывода сообщения трижды со смещением на пиксель, не знаю насколько красивое решение, но работает.
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. и заполняем поля
После чего запуск с точки зрения IDE приобретает такой вид: proxychains python3 app.py — собственно это нам и надо. Таким образом, когда мы хотим заняться проектом все что нужно сделать — запустить скрипт на рабочем столе, а потом для запуска бота нажать кнопку “play" в ide. Всю остальную магию сделают proxychains и ssh.
Наконец бот написан, оттестирован. Что дальше? С одной стороны хочется заявить о себе, с другой стороны, я думаю, он реально может кому-то пригодиться. И тут мы сталкиваемся с еще одной проблемой Телеграм; у него нет единого каталога каналов и ботов. Вполне возможно бот подобный моему существует, но повторюсь я его не нашел. А где-то в трамвае сидит и мучается человек, которому хочется красиво оформить сообщение в канал и он все делает ручками.
Если вы уже запустили мой бот, то увидели, что есть хэштег #Реклама. Как же так? — спросите вы. А тут я пошел на поводу у конечных пользователей — многие выкладывают рекламу в своих каналах и быстро привыкнув к оформлению сообщений с помощью бота, попросили добавить. Рекламу можно не любить, бороться с ней, но это суровые и необходимые для пользователей реалии.
Проект некоммерческий, поэтому думаю можно назвать сам бот @SGK_espace_bot.
А тут видео как пользоваться
Буду благодарен за любую конструктивную критику.
Комментарии (37)
gecube
24.11.2019 00:27+3Могу предложить другую схему?
Выкинуть все, что Вы использовали.
Оставить:
- Сервер на digitalocean — будем на него деплоить scp, там будет крутиться наш бот. Можно взять не DO, а heroku или любое другое аналогичное решение.
- Gitlab — в нем мы можем хранить код (безлимитное количество приватных репозиториев). Также гитлаб поможет нам собирать код и деплоить его на сервер из п.1.
Разработку можно вести прямо в WebIDE гитлаба. Она поддерживает подсветку синтаксиса python. И вряд ли интерфейс WebIDE гитлаба будет сильно хуже редактора прямо на самом смартфоне.
SGKond Автор
24.11.2019 07:46Когда использовал heroku, я даже с компа иной раз правил код сразу в GitHub.
SGKond Автор
24.11.2019 13:58Сейчас деплой происходит так: локально билдится контейнер и выкатывается на docker hub, затем с помощью ansible прогоняется плейбук по виртуалке в hetzner. Он пуллит с докерхаба образ и сравнивает с текущим, если есть изменения то перезапускает systemd unit сервис, который перезапускает докер контейнер с ботом. Планируется еще сделать чтобы по пушу в гитхаб сборка контейнера и выкатка в докерхаб была автоматом, с наскока не разобрался. Github вполне не хуже gitlab, а потому абсолютно нет смысла менять инструмент.
gecube
24.11.2019 14:04Полностью солидарен с тем, что "Github вполне не хуже gitlab". Но тут нюанс, что пока еще github не полностью self-contained решение. В случае гитлаба — там же можно хранить образы докеров, не заливая их на докер-хаб, к тому же докер-хаб для более 1 приватного регистри — платен. Можете сами решить насколько это приемлемо, я не навязываю какой-либо конкретный продукт.
Планируется еще сделать чтобы по пушу в гитхаб сборка контейнера и выкатка в докерхаб была автоматом, с наскока не разобрался
ну, либо настраивать интеграцию со стороны докерхаба, либо можно воспользоваться github actions. Варианты ± равноценные.
bykvaadm
24.11.2019 14:10+1В связи с последними событиями в gitlab, его использовать вообще не очень приятно.
Для данной задачи кмк вообще инструмент хранения кода не особо важен, поэтому нет смысла особо зацикливаться гитлаб или гитхаб. Ну и смущает вендор лок — завязываться на том что вендор дает все что вы описали сегодня бесплатно может вылиться в то что завтра придется с горящей жопой искать новый набор решений, потому что в любой момент гитлаб может изменить условия игры.gecube
24.11.2019 14:34Это относится к любому 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.
wxmaper
24.11.2019 08:51"Как я писал бота" вижу. Взгляда на современное программирование спустя 25 лет перерыва не вижу, а было бы интересно. Или этот взгляд описывается терниями с vpn/proxy и ркн?
SGKond Автор
24.11.2019 09:22Нет красоты кода, о ресурсах никто не заботится. Хотя красоту скорее всего может увидеть извращенец мазохист. До меня очень быстро дошел смысл фразы знакомого программиста “Посмотри прогу, может быть разберешься”. Самый главный взрыв мозга у меня был, когда я наконец то осознал, что код событийный, а не последовательный. Это другой уровень.
Вторая проблема отсутствие хорошей документации. Даже на басурманском.
Непредсказуемый результат как в примере с message.chat.id.
Решил дописать. Вот есть задумка добавить водяной знак на видео. Как найти библиотеку которая поможет? Или какая библиотека работает с html? И просто риторический вопрос — почему тот же Дуров не предусмотрел единой базы каналов и ботов?lair
24.11.2019 11:10+1Нет красоты кода, о ресурсах никто не заботится.
Это вы посмотрели код каких-то ботов, и на основании этого делаете выводы о современном программировании?
Вторая проблема отсутствие хорошей документации.
Хорошей документации на что?
Вот есть задумка добавить водяной знак на видео. Как найти библиотеку которая поможет?
Или какая библиотека работает с html?
SGKond Автор
24.11.2019 11:24Вторая проблема отсутствие хорошей документации.
<<Хорошей документации на что?>>
Извините, а примеров в статье недостаточно?lair
24.11.2019 11:27+1Нет. Потому что, насколько я могу понять по вашему тексту, подавляющая часть ваших претензий — к апи телеграма и/или какой-то реализующей его библиотеке.
SGKond Автор
24.11.2019 11:53С чем столкнулся о том и написал. И слово то какое нехорошее "претензии".
lair
24.11.2019 11:58И слово то какое нехорошее "претензии".
Такое же, как "проблема".
С чем столкнулся о том и написал.
Ну то есть вы столкнулись с проблемой в какой-то конкретной области, а пишете о "современном программировании"?
SGKond Автор
24.11.2019 12:30-1- Если бы все так было просто, то не существовало бы два разных слова.
- Предложите другое, более полное название статьи. ИМХО в названии есть все "необходимые и достаточные условия"
lair
24.11.2019 12:38Если бы все так было просто, то не существовало бы два разных слова.
Так я и не говорю, что это одинаковые слова, я говорю, что одно из них не более "нехорошее", чем другое.
Предложите другое, более полное название статьи.
О, это очень просто. "Как я писал бота для Телеграм после 25 лет перерыва в программировании".
SGKond Автор
24.11.2019 12:46-1Иезуиты аплодируют. Надо понимать что в название уже заложено отношение (видение) автора к проблеме.
gecube
24.11.2019 12:38Эджайл манифест.
Хороший продукт — важнее хорошей документации.
Это не означает, что последней не должно быть в принципе, но в условиях сжатого TTM документация без продукта нафиг никому не нужна. Поэтому имеем, что имеем
SGKond Автор
24.11.2019 11:55Вот есть задумка добавить водяной знак на видео. Как найти библиотеку которая поможет?
video watermarking in python
Или какая библиотека работает с html?
html processing in python
Спасибо.
StudyHelp
24.11.2019 10:51+1Очень сомнительным решением выглядит загрузка видео с YouTube, очистка его от рекламы и выкладывание на свой канал. Да ещё и со своими водяными знаками. Во-первых, права на такое действие автор видео явно не передавал (если в подписи к видео не указано иное… Ну или если нет прямой договоренности с автором). Во-вторых, на создание видео были потрачены усилия, время и, вполне вероятно, деньги. Так что автор имеет полное право поставить рекламу в видео, чтобы хотя бы попытаться выйти в ноль (а может и в плюс) по затратам. Это не неуважение к пользователю, это просто желание получить условно-справедливую оплату за свою работу. А лишать авторов контента этого — ну, такое себе… Кто-то из-за этого (снижение заработков) может просто перестать записывать и выкладывать интересные ролики.
SGKond Автор
24.11.2019 11:22- Пока в боте не реализована возможность делать водяной знак на видео. Хотя думаю сделать, т.к. часто вижу свои ролики без ссылок на источник. :-)
- Рассмотрим ситуацию:… имея дома нож я что потенциальный Чикотила? Передав кому то нож — я тоже являюсь пособником преступления? Нет — а уж хлеб им режут или кого то, я не могу нести ответственности.
lair
24.11.2019 11:11+2Тут же столкнулся с интересным моментом: хотя шрифт и является неотъемлемой частью библиотеки PIL, так как в первой строке написано локально работает, а в Docker — нет.
ImageFont.truetype("Pillow/Tests/fonts/FreeMono.ttf", width//20)
Вы, я так понимаю, с тем, где и как размещаются пакеты в python разбираться не стали? И слово
Tests
в пути вас тоже не смутило?SGKond Автор
24.11.2019 11:31К сожалению не стал и не смутило. За месяц я переварил такой объем инфы, что иногда на ровном месте делал глупости. Я никогда не работал раньше с Линуксом, не знал даже слов Python, github, heroku, имел представление о прокси как банальный эрудит, а знакомство с VPN сводилось исключительно к использованию ТОР браузера.
t0rr
25.11.2019 11:33+2pyTelegramBotAPI — Одна из основных библиотек при написании бота для Телеграм.
Ну зачем так-то?
Есть же aiogram:
- со своевременными обновлениями (день в день с релизами Teleram Bot API)
- с async, а не с воркерами на тредах
- с готовыми решениями (FSM, LeakyBucket и др.)
- с готовыми интеграциями (Redis, Mongo и др.)
- с русскоязычным сообществом
+ В статье было бы уместно сослаться на перечень библиотек/фреймворков, опубликованный в документации Telegram:
core.telegram.org/bots/samples
SGKond Автор
25.11.2019 20:22-1Да, надо переползать
https://docs.telethon.dev/en/latest/
https://aiogram.readthedocs.io/en/latest/search.html?q=download&check_keywords=yes&area=default
Пишу с мобилы — простите за стиль.
delon_reney
26.11.2019 09:26Наконец бот написан, оттестирован.
За первые пару минут пользования ботом наткнулся на пару весьма неприятных багов, которые убивают весь функционал Вашего бота:
- После первой отправки боту изображения — оно возвращается корректно. При последующих отправках возвращается всё та же картинка из первого сообщения
- При попытке загрузить видео с YouTube, независимо от ссылки, в ответ ты всегда получаешь Гену с Чебурашкой
А тут я пошел на поводу у конечных пользователей — многие выкладывают рекламу в своих каналах и быстро привыкнув к оформлению сообщений с помощью бота, попросили добавить
Не совсем ясно, какие такие пользователи привыкли к «оформлению сообщений с помощью бота», если обе его функции практически полностью нерабочие.SGKond Автор
26.11.2019 09:27Я вчера его "сломал". Сегодня буду разбираться, что случилось. Приношу извинения. Проект не коммерческий. :-)
diogen4212
26.11.2019 09:43При попытке загрузить видео с YouTube, независимо от ссылки, в ответ ты всегда получаешь Гену с Чебурашкой
тонкий намёк на грядущий Чебурнет....SGKond Автор
26.11.2019 09:51Исправил. Тестируйте. Не тот релиз выложил. Просто у меня будет еще водяной знак на видео и автоматическая подготовка статьи с новостных сайтов для публикации в канал
SGKond Автор
26.11.2019 20:22Добавил
import moviepy
from moviepy.editor import *
и все порушилось. Думаю автоматически подгрузилась OS из moviepy
pawnhearts
Я написал github.com/pawnhearts/lctelegate полностью на смартфоне. Тестил запуская по ssh.
SGKond Автор
Я не смог. При зрении -3 не ношу очки.