В прошлой статье я научил старенький Samsung ML-1615 печатать по AirPrint. Удобно, но только пока ты дома. А хочется так: переслал документ в семейный чат с подписью «напечатай», пришёл домой, а он уже лежит в лотке. Сделал) Идём под кат…
Как устроено
Телеграм-бот у меня уже есть, его слушает Home Assistant. Через него приходят уведомления, через него же magnet-ссылки из чата уезжают в qBittorrent. Второго слушателя на одного бота Telegram не пускает, поэтому всё вешаем на HA. Он ловит сообщение с файлом, скачивает файл и отдаёт его маленькому HTTP-серверу в контейнере с CUPS, а тот отправляет файл на печать.

Что ловить в Home Assistant
Тут есть тонкость. Обычный текст HA присылает событием telegram_text, а сообщение с файлом отдельным событием telegram_attachment. Подпись к файлу лежит в том же поле text, рядом с file_id, file_name и прочим, так что слово «напечатай» проверяется как в обычном сообщении.
Если не уверены, что именно прилетает, включите debug-лог интеграции Telegram Bot. В логе будет строчка Firing event telegram_attachment: {...} со всеми полями.
Сервер печати
В контейнере с CUPS крутится крошечный сервер на голом http.server из стандартной библиотеки Python, строк на 60. Умеет ровно одно:
POST /print
X-Print-Secret: <секрет>
X-File-Name: <имя файла>
<тело — сырые байты документа>
→ lp -d ML1615 <файл>
→ {"ok": true}
Наружу через роутер порт не проброшен, слушается только локалка. Без общего секрета в заголовке сервер отвечает 403. Сам секрет лежит в файле с правами 600. Сверху systemd-юнит с Restart=on-failure.
Связка в Home Assistant
Автоматизация проверяет, что сообщение пришло из нужного чата и в подписи есть «напечатай»:
automation:
- alias: "Печать документа из Telegram"
trigger:
- platform: event
event_type: telegram_attachment
condition:
- condition: template
value_template: "{{ trigger.event.data.chat_id == <ID вашего чата> }}"
- condition: template
value_template: "{{ 'напечатай' in (trigger.event.data.text | default('')) | lower }}"
action:
- service: shell_command.print_telegram_file
data:
file_id: "{{ trigger.event.data.file_id }}"
file_name: "{{ trigger.event.data.file_name }}"
А shell-команда берёт у Telegram путь к файлу, скачивает его и отправляет на печать:
shell_command:
print_telegram_file: >
bash -c '
FILE_PATH=$(curl -s "https://api.telegram.org/bot<ТОКЕН>/getFile?file_id={{ file_id }}" | python3 -c "import sys,json;print(json.load(sys.stdin)[\"result\"][\"file_path\"])") &&
curl -s -o /tmp/tg_print_file "https://api.telegram.org/file/bot<ТОКЕН>/$FILE_PATH" &&
curl -s -X POST "http://<IP контейнера>:9199/print" -H "X-Print-Secret: <секрет>" -H "X-File-Name: {{ file_name }}" --data-binary @/tmp/tg_print_file
'
Что получилось
Пересылаю в семейный чат PDF с подписью «напечатай», и лист выезжает из принтера, пока я ещё смотрю в телефон. Работает откуда угодно, где есть Telegram, и никаких VPN и проброшенных портов не понадобилось.
Если вдруг перестанет печатать, смотрю по порядку: дошло ли событие до HA (debug-лог telegram_bot), дошёл ли запрос до сервера печати (журнал его systemd-юнита), а дальше уже CUPS.
