rpi: скачать Бёрта Уандерстоуна и уведомить о готовности

This commit is contained in:
2026-10-18 12:58:46 +03:00
parent 19f957f1c6
commit 5132ef8c63
4 changed files with 92 additions and 0 deletions
+2
View File
@@ -84,6 +84,8 @@ OneDrive на внешний HDD; с того же дня ещё и медиац
- Для перевёрстки извлечённого текста в PDF установлен `python3-reportlab` 4.3.1 (2026-10-11; ранее средств создания PDF с кириллицей не было), с зависимостями Pillow/Cairo. Шрифт DejaVu Sans внедряется в PDF; PNG-предпросмотр строится из итогового серого PDF. Проверено на комплекте Лермонтова: 3 страницы A4, текст со скриншотов и исходный портрет.
## Медиацентр (с 2026-10-11, код — `stacks/rpi-media/`)
- 2026-10-18 по просьбе владельца добавлен «Невероятный Бёрт Уандерстоун» (2013, TMDB 124459, Radarr id=3), вручную выбрана RuTracker-раздача BDRip 1080p MVO + Original Eng RUS, 11,4 ГБ. Установлен `notify-movie-ready.timer` (раз в 2 мин, ранее уведомления для этого фильма не было): после импорта с русской аудиодорожкой и появления в Jellyfin отправляет владельцу 607015 ссылку на фильм. Скрипт и юниты — `stacks/rpi-media/`; отметка доставки `/var/lib/media-ready/burt-wonderstone.sent`, после неё повторно не шлёт. Секреты читает из существующих env, в логах только тип ошибки, чтобы не раскрыть Telegram URL с токеном. ⚠️ Ссылка доступна в домашней сети; таймер не означает, что загрузка уже завершилась.
Docker CE 29.9 + Compose v5.6 из репо download.docker.com (в Debian старее). `/etc/docker/daemon.json`: json-file `10m×3` — чтобы логи контейнеров не точили SD. `rus` в группе `docker` (= root-эквивалент; у него и так sudo NOPASSWD). Стек — `/opt/media/docker-compose.yml`, конфиги — `/opt/media/config/<сервис>` (SD, ~20 МБ), образы ~7.8 ГБ на SD.
| Сервис | Порт | Зачем | Версия на 2026-10-11 |
@@ -0,0 +1,14 @@
[Unit]
Description=Notify owner when Burt Wonderstone is ready in Jellyfin
After=network-online.target docker.service
[Service]
Type=oneshot
ExecStart=/usr/bin/python3 /usr/local/lib/media-ready/notify-movie-ready.py
StateDirectory=media-ready
UMask=0077
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
TimeoutStartSec=120
+10
View File
@@ -0,0 +1,10 @@
[Unit]
Description=Check requested movie readiness every two minutes
[Timer]
OnBootSec=2min
OnUnitInactiveSec=2min
Unit=notify-movie-ready.service
[Install]
WantedBy=timers.target
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""Send one owner notification after Radarr import and Jellyfin indexing."""
import json
from pathlib import Path
import urllib.request
TMDB = 124459
STATE = Path('/var/lib/media-ready/burt-wonderstone.sent')
def env(path):
return dict(line.strip().split('=', 1) for line in open(path)
if '=' in line and not line.startswith('#'))
def api(base, path, headers=None, data=None):
request = urllib.request.Request(base + path, headers=headers or {},
data=None if data is None else json.dumps(data).encode())
with urllib.request.urlopen(request, timeout=30) as response:
body = response.read()
return json.loads(body) if body else None
def main():
if STATE.exists():
return
keys = env('/etc/media.env')
movies = api('http://127.0.0.1:7878', '/api/v3/movie',
{'X-Api-Key': keys['RADARR_KEY']})
movie = next((m for m in movies if m['tmdbId'] == TMDB), None)
if not movie or not movie.get('hasFile'):
print('Waiting for Radarr import')
return
audio = str(movie.get('movieFile', {}).get('mediaInfo', {}).get('audioLanguages', '')).lower()
if not any(language in audio.replace('/', ' ').replace(',', ' ').split()
for language in ('russian', 'rus', 'ru')):
print('Waiting for an imported file with Russian audio')
return
base = 'http://127.0.0.1:8096'
headers = {'Authorization': 'MediaBrowser Token="' + keys['JELLYFIN_KEY'] + '"'}
items = api(base, '/Items?Recursive=true&IncludeItemTypes=Movie&Fields=ProviderIds', headers)
item = next((i for i in items['Items']
if i.get('ProviderIds', {}).get('Tmdb') == str(TMDB)), None)
if not item:
api(base, '/Library/Refresh', headers, {})
print('Waiting for Jellyfin index; refresh requested')
return
server = api(base, '/System/Info/Public')['Id']
link = ('http://192.168.10.25:8096/web/#/details?id='
+ item['Id'] + '&serverId=' + server)
token = env('/etc/astra-bot.env')['TG_TOKEN']
result = api('https://api.telegram.org', '/bot' + token + '/sendMessage',
{'Content-Type': 'application/json'},
{'chat_id': 607015, 'text': '«Невероятный Бёрт Уандерстоун» скачался. '
'Русская озвучка, 1080p. Смотреть дома:\n' + link,
'disable_web_page_preview': True})
if not result.get('ok'):
raise RuntimeError('Telegram did not confirm delivery')
STATE.parent.mkdir(parents=True, exist_ok=True)
STATE.write_text(str(result['result']['message_id']) + '\n')
print('Ready notification delivered')
if __name__ == '__main__':
# urllib exceptions can contain the Telegram token in their URL.
try:
main()
except Exception as error:
print('Movie notification failed: ' + type(error).__name__)
raise SystemExit(1)