rpi-media: стартовая страница Homepage, Radarr/Sonarr → Jellyfin connect
- homepage/: сервисы с описанием и живыми виджетами; ключи — в homepage.env на малине - Jellyfin-виджет через customapi (встроенный не совместим с Jellyfin 12) - provision.py: шаги homepage и connect Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
b915a58ad9
commit
e02a9a8f1b
@@ -6,7 +6,7 @@
|
|||||||
- [`servers/de1.md`](servers/de1.md) — 213.136.74.247. **Выведен** (все сервисы остановлены, метрики удалены): был прокси/VPN-нодой (telemt, AmneziaWG, OpenVPN) плюс gitea, openclaw, боты — всё уехало на fr1 или в бэкапы. ⚠️ Сам файл описания под вывод не переписан.
|
- [`servers/de1.md`](servers/de1.md) — 213.136.74.247. **Выведен** (все сервисы остановлены, метрики удалены): был прокси/VPN-нодой (telemt, AmneziaWG, OpenVPN) плюс gitea, openclaw, боты — всё уехало на fr1 или в бэкапы. ⚠️ Сам файл описания под вывод не переписан.
|
||||||
- [`servers/fr1.md`](servers/fr1.md) — `fr1.ruzzy.dev` (161.97.93.252). Основная нода (Ubuntu 24.04): мониторинг, gitea, AmneziaWG exit для ru1, боты (claude-channels, openclaw), статика `www`/`share`. Держит апекс `ruzzy.dev`.
|
- [`servers/fr1.md`](servers/fr1.md) — `fr1.ruzzy.dev` (161.97.93.252). Основная нода (Ubuntu 24.04): мониторинг, gitea, AmneziaWG exit для ru1, боты (claude-channels, openclaw), статика `www`/`share`. Держит апекс `ruzzy.dev`.
|
||||||
- [`servers/ru1.md`](servers/ru1.md) — `85.198.109.86` (VDSina, РФ). VPN entry-нода (OpenVPN ×2, AmneziaWG **до fr1** после переключения, WireGuard клиентов), умный роутинг RU/зарубеж; WEB-прокси Telegram (tproxy-server + MTProxy) на `ru.ruzzy.dev:443`, telemt удалён 2026-10-09. ⚠️ Файл описания сверялся до переключения.
|
- [`servers/ru1.md`](servers/ru1.md) — `85.198.109.86` (VDSina, РФ). VPN entry-нода (OpenVPN ×2, AmneziaWG **до fr1** после переключения, WireGuard клиентов), умный роутинг RU/зарубеж; WEB-прокси Telegram (tproxy-server + MTProxy) на `ru.ruzzy.dev:443`, telemt удалён 2026-10-09. ⚠️ Файл описания сверялся до переключения.
|
||||||
- [`servers/rpi.md`](servers/rpi.md) — `rpi.local` (192.168.10.25, дом, за NAT). Raspberry Pi 4: бэкап личного OneDrive на HDD 4 ТБ (rclone, вечный архив версий, еженедельная сверка хэшей); SMART и статус бэкапов пушит в pushgateway fr1 по SSH. Код — `stacks/rpi-backup/`. Агент Astra (Codex) с управлением из Telegram — репо `ruzzy/astra-bot`. Медиацентр в Docker (Jellyfin, Seerr, qBittorrent, Radarr/Sonarr/Prowlarr/Bazarr) — `stacks/rpi-media/`.
|
- [`servers/rpi.md`](servers/rpi.md) — `rpi.local` (192.168.10.25, дом, за NAT). Raspberry Pi 4: бэкап личного OneDrive на HDD 4 ТБ (rclone, вечный архив версий, еженедельная сверка хэшей); SMART и статус бэкапов пушит в pushgateway fr1 по SSH. Код — `stacks/rpi-backup/`. Агент Astra (Codex) с управлением из Telegram — репо `ruzzy/astra-bot`. Медиацентр в Docker (Jellyfin, Seerr, qBittorrent, Radarr/Sonarr/Prowlarr/Bazarr, стартовая страница Homepage :3000) — `stacks/rpi-media/`.
|
||||||
|
|
||||||
## Поддержание описаний в актуальном состоянии
|
## Поддержание описаний в актуальном состоянии
|
||||||
Тронул сервер — обнови `servers/<хост>.md` в том же прогоне. Контракт и
|
Тронул сервер — обнови `servers/<хост>.md` в том же прогоне. Контракт и
|
||||||
|
|||||||
+5
-1
@@ -88,6 +88,7 @@ Docker CE 29.9 + Compose v5.6 из репо download.docker.com (в Debian ст
|
|||||||
| Prowlarr | 9696 | индексаторы, раздаёт их в Radarr/Sonarr | 2.6.5 |
|
| Prowlarr | 9696 | индексаторы, раздаёт их в Radarr/Sonarr | 2.6.5 |
|
||||||
| FlareSolverr | 8191 | обход Cloudflare для индексаторов с тегом `flaresolverr` | v3.5.2 |
|
| FlareSolverr | 8191 | обход Cloudflare для индексаторов с тегом `flaresolverr` | v3.5.2 |
|
||||||
| Bazarr | 6767 | субтитры, профиль `ru+en` | v1.6.2 |
|
| Bazarr | 6767 | субтитры, профиль `ru+en` | v1.6.2 |
|
||||||
|
| Homepage | 3000 | **стартовая страница**: все сервисы с описанием по-русски, живой статус, CPU/температура/диск | v2.5.0 |
|
||||||
|
|
||||||
- **Данные — `/mnt/backup/media`** (4-ТБ диск, решение пользователя): `torrents/{movies,tv,other}`, `library/{movies,tv}`, `.cache/jellyfin` (кэш и транскоды Jellyfin — не на SD). qBittorrent и *arr монтируют **один и тот же** корень как `/data` — иначе импорт из `torrents/` в `library/` превращается из хардлинка в копию и раздача занимает место дважды. `copyUsingHardlinks` включён. В бэкапы (`router-backup`, `onedrive-*`) `media/` не входит.
|
- **Данные — `/mnt/backup/media`** (4-ТБ диск, решение пользователя): `torrents/{movies,tv,other}`, `library/{movies,tv}`, `.cache/jellyfin` (кэш и транскоды Jellyfin — не на SD). qBittorrent и *arr монтируют **один и тот же** корень как `/data` — иначе импорт из `torrents/` в `library/` превращается из хардлинка в копию и раздача занимает место дважды. `copyUsingHardlinks` включён. В бэкапы (`router-backup`, `onedrive-*`) `media/` не входит.
|
||||||
- ⚠️ **Медиа делят диск с бэкапами.** `onedrive-backup` падает с кодом 2 при заполнении >90 % (~370 ГБ свободно) → `BackupFailed`. В Radarr/Sonarr стоит `minimumFreeSpaceWhenImporting = 500 ГБ`: ниже этого импорт останавливается. **qBittorrent своего порога не имеет** — ручная заливка торрентов мимо *arr может забить диск.
|
- ⚠️ **Медиа делят диск с бэкапами.** `onedrive-backup` падает с кодом 2 при заполнении >90 % (~370 ГБ свободно) → `BackupFailed`. В Radarr/Sonarr стоит `minimumFreeSpaceWhenImporting = 500 ГБ`: ниже этого импорт останавливается. **qBittorrent своего порога не имеет** — ручная заливка торрентов мимо *arr может забить диск.
|
||||||
@@ -97,7 +98,10 @@ Docker CE 29.9 + Compose v5.6 из репо download.docker.com (в Debian ст
|
|||||||
- ⚠️ RuTracker закрывает `login.php`/`tracker.php` челленджем Cloudflare (по IPv4; IPv6 у малины нет маршрута). FlareSolverr на Pi решает его **80–180 с** — у прокси в Prowlarr `requestTimeout=180` (было 60, с ним добавление падало по таймауту). После решения Prowlarr держит cookie и поиск идёт ~4 с; когда cookie протухнет, первый поиск снова будет минутами, и *arr могут на время пометить индексатор недоступным.
|
- ⚠️ RuTracker закрывает `login.php`/`tracker.php` челленджем Cloudflare (по IPv4; IPv6 у малины нет маршрута). FlareSolverr на Pi решает его **80–180 с** — у прокси в Prowlarr `requestTimeout=180` (было 60, с ним добавление падало по таймауту). После решения Prowlarr держит cookie и поиск идёт ~4 с; когда cookie протухнет, первый поиск снова будет минутами, и *arr могут на время пометить индексатор недоступным.
|
||||||
- Bazarr: провайдеры без аккаунтов (`embeddedsubtitles`, `podnapisi`, `yifysubtitles`); для русских субтитров лучший — OpenSubtitles.com, нужен аккаунт.
|
- Bazarr: провайдеры без аккаунтов (`embeddedsubtitles`, `podnapisi`, `yifysubtitles`); для русских субтитров лучший — OpenSubtitles.com, нужен аккаунт.
|
||||||
- **Авторизация:** везде пользователь `rus`, один пароль — `/opt/media/.admin-password` (rus 600). *arr — формы, пароль **всегда** (режим «без пароля из LAN» в новых *arr требует `AllowedHosts`). Между собой сервисы ходят по API-ключам из `config/<app>/config.xml`.
|
- **Авторизация:** везде пользователь `rus`, один пароль — `/opt/media/.admin-password` (rus 600). *arr — формы, пароль **всегда** (режим «без пароля из LAN» в новых *arr требует `AllowedHosts`). Между собой сервисы ходят по API-ключам из `config/<app>/config.xml`.
|
||||||
- Первичная связка — `stacks/rpi-media/provision.py` (идемпотентный, пароль и ключи читает на месте): `python3 /opt/media/provision.py [qbit jellyfin arr prowlarr bazarr seerr]`.
|
- **Точка входа для пользователя — http://192.168.10.25:3000** (Homepage, конфиги `stacks/rpi-media/homepage/` → `/opt/media/homepage/`). Ключи виджетов — `/opt/media/homepage.env` (rus 600, `HOMEPAGE_VAR_*`, генерит `provision.py homepage`). ⚠️ Там же пароль qBittorrent: после смены общего пароля перегенерировать env и `docker compose up -d homepage`, иначе виджет qBittorrent отвалится. `HOMEPAGE_ALLOWED_HOSTS` обязателен — без него 400 на любой Host, кроме localhost.
|
||||||
|
- ⚠️ Встроенный виджет `jellyfin` Homepage 2.5 с Jellyfin 12 не работает: ходит на `/emby/…?api_key=` — пути нет (404), ключ в query отключён (`EnableLegacyAuthorization=false`, включать не стали). Вместо него `customapi` на `/Items/Counts` с заголовком `Authorization: MediaBrowser Token=…`.
|
||||||
|
- Radarr/Sonarr → Jellyfin (Connect «Jellyfin», тип MediaBrowser, ключ Jellyfin `homepage`; `provision.py connect` на чистой установке заводит ключ `arr-connect`): библиотека обновляется сразу после импорта. Без этого новый фильм висел невидимым до скана по расписанию — realtime-монитор хардлинк не заметил (проверено 2026-10-11 на первом фильме).
|
||||||
|
- Первичная связка — `stacks/rpi-media/provision.py` (идемпотентный, пароль и ключи читает на месте): `python3 /opt/media/provision.py [qbit jellyfin arr prowlarr bazarr seerr connect homepage]`.
|
||||||
- ⚠️ Каталог `config/<сервис>`, которого нет до `up`, docker создаёт **от root** — Jellyfin/Seerr (uid 1000) падают с `Permission denied`. Новые каталоги создавать заранее или `chown -R rus:rus /opt/media/config`.
|
- ⚠️ Каталог `config/<сервис>`, которого нет до `up`, docker создаёт **от root** — Jellyfin/Seerr (uid 1000) падают с `Permission denied`. Новые каталоги создавать заранее или `chown -R rus:rus /opt/media/config`.
|
||||||
- ⚠️ `fallenbagel/jellyseerr` заброшен (последний образ 2025-08) и не логинится в Jellyfin 12 — заменён на `ghcr.io/seerr-team/seerr`.
|
- ⚠️ `fallenbagel/jellyseerr` заброшен (последний образ 2025-08) и не логинится в Jellyfin 12 — заменён на `ghcr.io/seerr-team/seerr`.
|
||||||
- Торренты идут **напрямую** с домашнего IP (решение пользователя 2026-10-11; вариант через AWG fr1 отложен). Порт 6881 на роутере **не проброшен** — входящих соединений нет, раздача и скорость хуже.
|
- Торренты идут **напрямую** с домашнего IP (решение пользователя 2026-10-11; вариант через AWG fr1 отложен). Порт 6881 на роутере **не проброшен** — входящих соединений нет, раздача и скорость хуже.
|
||||||
|
|||||||
Binary file not shown.
@@ -110,3 +110,21 @@ services:
|
|||||||
- ./config/seerr:/app/config
|
- ./config/seerr:/app/config
|
||||||
ports:
|
ports:
|
||||||
- "5055:5055"
|
- "5055:5055"
|
||||||
|
|
||||||
|
homepage:
|
||||||
|
# стартовая страница со всеми сервисами, описаниями и живым статусом
|
||||||
|
image: ghcr.io/gethomepage/homepage:latest
|
||||||
|
container_name: homepage
|
||||||
|
restart: unless-stopped
|
||||||
|
env_file: ./homepage.env # HOMEPAGE_VAR_* — API-ключи и пароль qBittorrent, rus 600, только на малине
|
||||||
|
environment:
|
||||||
|
TZ: Europe/Moscow
|
||||||
|
PUID: "1000"
|
||||||
|
PGID: "1000"
|
||||||
|
# без этого отдаёт 400 на любой Host, кроме localhost
|
||||||
|
HOMEPAGE_ALLOWED_HOSTS: 192.168.10.25:3000,rpi.local:3000,localhost:3000
|
||||||
|
volumes:
|
||||||
|
- ./homepage:/app/config
|
||||||
|
- /mnt/backup:/mnt/backup:ro # только чтобы виджет resources видел заполнение диска
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
[]
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# Ключи — из /opt/media/homepage.env (HOMEPAGE_VAR_*), в репо их нет.
|
||||||
|
# Ссылки (href) — для браузера, адрес малины; виджеты ходят изнутри docker-сети по именам
|
||||||
|
# контейнеров, кроме Jellyfin (он в host-сети).
|
||||||
|
|
||||||
|
- Как это работает:
|
||||||
|
- 1. Найти:
|
||||||
|
icon: mdi-magnify
|
||||||
|
description: "Открой Seerr, найди фильм или сериал (можно по-русски) и нажми Request"
|
||||||
|
- 2. Скачать:
|
||||||
|
icon: mdi-download
|
||||||
|
description: "Radarr/Sonarr сами ищут раздачу на трекерах, qBittorrent качает. Минуты–час"
|
||||||
|
- 3. Смотреть:
|
||||||
|
icon: mdi-television-play
|
||||||
|
description: "Готовое появляется в Jellyfin; субтитры ru/en Bazarr докачает сам"
|
||||||
|
- Если застряло:
|
||||||
|
icon: mdi-help-circle-outline
|
||||||
|
description: "Radarr/Sonarr → Activity → Queue; красная карточка = раздачи нет → Interactive Search"
|
||||||
|
|
||||||
|
- Смотреть:
|
||||||
|
- Jellyfin:
|
||||||
|
icon: jellyfin.svg
|
||||||
|
href: http://192.168.10.25:8096
|
||||||
|
description: "Медиатека. На LG — приложение Jellyfin, на iPhone/iPad — Infuse или Swiftfin, сервер 192.168.10.25:8096"
|
||||||
|
# ⚠️ встроенный виджет jellyfin (Homepage 2.5) ходит на /emby/…?api_key= — в Jellyfin 12 этого
|
||||||
|
# пути нет (404), а ключ в query отключён (EnableLegacyAuthorization=false). Поэтому customapi.
|
||||||
|
widget:
|
||||||
|
type: customapi
|
||||||
|
url: http://192.168.10.25:8096/Items/Counts
|
||||||
|
headers:
|
||||||
|
Authorization: 'MediaBrowser Token="{{HOMEPAGE_VAR_JELLYFIN_KEY}}"'
|
||||||
|
mappings:
|
||||||
|
- field: MovieCount
|
||||||
|
label: Фильмы
|
||||||
|
format: number
|
||||||
|
- field: SeriesCount
|
||||||
|
label: Сериалы
|
||||||
|
format: number
|
||||||
|
- field: EpisodeCount
|
||||||
|
label: Серии
|
||||||
|
format: number
|
||||||
|
- Seerr:
|
||||||
|
icon: jellyseerr.svg
|
||||||
|
href: http://192.168.10.25:5055
|
||||||
|
description: "Каталог «хочу посмотреть»: Request → скачается само. Статусы: Processing → Available"
|
||||||
|
widget:
|
||||||
|
type: jellyseerr
|
||||||
|
url: http://seerr:5055
|
||||||
|
key: "{{HOMEPAGE_VAR_SEERR_KEY}}"
|
||||||
|
|
||||||
|
- Добавить фильм или сериал:
|
||||||
|
- Radarr — фильмы:
|
||||||
|
icon: radarr.svg
|
||||||
|
href: http://192.168.10.25:7878
|
||||||
|
description: "Очередь: Activity → Queue. Выбрать раздачу вручную: карточка → Interactive Search"
|
||||||
|
widget:
|
||||||
|
type: radarr
|
||||||
|
url: http://radarr:7878
|
||||||
|
key: "{{HOMEPAGE_VAR_RADARR_KEY}}"
|
||||||
|
- Sonarr — сериалы:
|
||||||
|
icon: sonarr.svg
|
||||||
|
href: http://192.168.10.25:8989
|
||||||
|
description: "Новые серии отслеживаемых сериалов качает сам. Очередь: Activity → Queue"
|
||||||
|
widget:
|
||||||
|
type: sonarr
|
||||||
|
url: http://sonarr:8989
|
||||||
|
key: "{{HOMEPAGE_VAR_SONARR_KEY}}"
|
||||||
|
- Bazarr — субтитры:
|
||||||
|
icon: bazarr.svg
|
||||||
|
href: http://192.168.10.25:6767
|
||||||
|
description: "Субтитры ru/en для всего в библиотеке; чего не хватает — Wanted"
|
||||||
|
widget:
|
||||||
|
type: bazarr
|
||||||
|
url: http://bazarr:6767
|
||||||
|
key: "{{HOMEPAGE_VAR_BAZARR_KEY}}"
|
||||||
|
|
||||||
|
- Загрузки и служебное:
|
||||||
|
- qBittorrent:
|
||||||
|
icon: qbittorrent.svg
|
||||||
|
href: http://192.168.10.25:8080
|
||||||
|
description: "Сами загрузки: скорость, сиды. Торренты вручную сюда — мимо Jellyfin и контроля места"
|
||||||
|
widget:
|
||||||
|
type: qbittorrent
|
||||||
|
url: http://qbittorrent:8080
|
||||||
|
username: "{{HOMEPAGE_VAR_QBIT_USER}}"
|
||||||
|
password: "{{HOMEPAGE_VAR_QBIT_PASS}}"
|
||||||
|
enableLeechProgress: true
|
||||||
|
- Prowlarr — трекеры:
|
||||||
|
icon: prowlarr.svg
|
||||||
|
href: http://192.168.10.25:9696
|
||||||
|
description: "RuTracker, NoNaMe Club, TPB, YTS… Ручной поиск по всем трекерам сразу"
|
||||||
|
widget:
|
||||||
|
type: prowlarr
|
||||||
|
url: http://prowlarr:9696
|
||||||
|
key: "{{HOMEPAGE_VAR_PROWLARR_KEY}}"
|
||||||
|
- FlareSolverr:
|
||||||
|
icon: flaresolverr.svg
|
||||||
|
href: http://192.168.10.25:8191
|
||||||
|
description: "Проходит проверку Cloudflare для RuTracker (на Pi — минуты). Трогать не нужно"
|
||||||
|
siteMonitor: http://flaresolverr:8191
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# Homepage — стартовая страница медиацентра, http://192.168.10.25:3000
|
||||||
|
title: Домашний медиацентр
|
||||||
|
language: ru
|
||||||
|
theme: dark
|
||||||
|
color: slate
|
||||||
|
headerStyle: clean
|
||||||
|
hideVersion: true
|
||||||
|
statusStyle: dot
|
||||||
|
quicklaunch:
|
||||||
|
searchDescriptions: true
|
||||||
|
layout:
|
||||||
|
Как это работает:
|
||||||
|
style: row
|
||||||
|
columns: 4
|
||||||
|
Смотреть:
|
||||||
|
style: row
|
||||||
|
columns: 2
|
||||||
|
Добавить фильм или сериал:
|
||||||
|
style: row
|
||||||
|
columns: 3
|
||||||
|
Загрузки и служебное:
|
||||||
|
style: row
|
||||||
|
columns: 4
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
- greeting:
|
||||||
|
text_size: xl
|
||||||
|
text: "Логин везде: rus · пароль общий"
|
||||||
|
- resources:
|
||||||
|
label: Малина
|
||||||
|
cpu: true
|
||||||
|
memory: true
|
||||||
|
cputemp: true
|
||||||
|
uptime: true
|
||||||
|
- resources:
|
||||||
|
label: Диск медиа (4 ТБ)
|
||||||
|
disk: /mnt/backup
|
||||||
|
- datetime:
|
||||||
|
text_size: l
|
||||||
|
locale: ru
|
||||||
|
format:
|
||||||
|
dateStyle: long
|
||||||
|
timeStyle: short
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
ничего не ломает, уже сделанное пропускает.
|
ничего не ломает, уже сделанное пропускает.
|
||||||
|
|
||||||
Запуск на малине: python3 /opt/media/provision.py [шаг ...]
|
Запуск на малине: python3 /opt/media/provision.py [шаг ...]
|
||||||
Шаги: qbit jellyfin arr prowlarr bazarr seerr (без аргументов — все).
|
Шаги: qbit jellyfin arr prowlarr bazarr seerr connect homepage (без аргументов — все).
|
||||||
Пароль админа берётся из /opt/media/.admin-password, API-ключи — из config.xml.
|
Пароль админа берётся из /opt/media/.admin-password, API-ключи — из config.xml.
|
||||||
"""
|
"""
|
||||||
from http.cookiejar import CookieJar
|
from http.cookiejar import CookieJar
|
||||||
@@ -256,6 +256,58 @@ def prowlarr():
|
|||||||
log("prowlarr ok")
|
log("prowlarr ok")
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------- Homepage + Jellyfin connect
|
||||||
|
def jf_apikey(name):
|
||||||
|
"""API-ключ Jellyfin для приложения name (создаётся при отсутствии)."""
|
||||||
|
tok = jf_token()
|
||||||
|
h = {"Authorization": f'{JF_AUTH}, Token="{tok}"'}
|
||||||
|
find = lambda: next((x["AccessToken"] for x in http("GET", JF + "/Auth/Keys", headers=h)[1]["Items"]
|
||||||
|
if x["AppName"] == name), None)
|
||||||
|
if not find():
|
||||||
|
http("POST", f"{JF}/Auth/Keys?app={name}", headers=h)
|
||||||
|
return find()
|
||||||
|
|
||||||
|
|
||||||
|
def homepage():
|
||||||
|
"""/opt/media/homepage.env (rus 600) — ключи для виджетов, в репо их нет."""
|
||||||
|
import os, yaml
|
||||||
|
env = {
|
||||||
|
"HOMEPAGE_VAR_JELLYFIN_KEY": jf_apikey("homepage"),
|
||||||
|
"HOMEPAGE_VAR_SEERR_KEY": json.load(open(f"{BASE}/config/seerr/settings.json"))["main"]["apiKey"],
|
||||||
|
"HOMEPAGE_VAR_RADARR_KEY": apikey("radarr"),
|
||||||
|
"HOMEPAGE_VAR_SONARR_KEY": apikey("sonarr"),
|
||||||
|
"HOMEPAGE_VAR_PROWLARR_KEY": apikey("prowlarr"),
|
||||||
|
"HOMEPAGE_VAR_BAZARR_KEY": yaml.safe_load(open(f"{BASE}/config/bazarr/config/config.yaml"))["auth"]["apikey"],
|
||||||
|
"HOMEPAGE_VAR_QBIT_USER": USER,
|
||||||
|
"HOMEPAGE_VAR_QBIT_PASS": PW,
|
||||||
|
}
|
||||||
|
old = os.umask(0o077)
|
||||||
|
open(f"{BASE}/homepage.env", "w").write("".join(f"{k}={v}\n" for k, v in env.items()))
|
||||||
|
os.umask(old)
|
||||||
|
log("homepage env written (перезапусти контейнер homepage, если ключи сменились)")
|
||||||
|
|
||||||
|
|
||||||
|
def connect():
|
||||||
|
"""Radarr/Sonarr → Jellyfin: обновить библиотеку сразу после импорта (иначе ждать скан по расписанию)."""
|
||||||
|
k = jf_apikey("arr-connect")
|
||||||
|
for name, a in ARR.items():
|
||||||
|
h = {"X-Api-Key": apikey(name)}
|
||||||
|
u = f"{a['url']}/api/{a['api']}"
|
||||||
|
st, ns = http("GET", u + "/notification", headers=h)
|
||||||
|
if any(n["implementation"] == "MediaBrowser" for n in ns):
|
||||||
|
continue
|
||||||
|
st, schema = http("GET", u + "/notification/schema", headers=h)
|
||||||
|
n = next(x for x in schema if x["implementation"] == "MediaBrowser")
|
||||||
|
vals = {"host": "192.168.10.25", "port": 8096, "useSsl": False, "apiKey": k, "notify": False, "updateLibrary": True}
|
||||||
|
for f in n["fields"]:
|
||||||
|
if f["name"] in vals:
|
||||||
|
f["value"] = vals[f["name"]]
|
||||||
|
n.update({"name": "Jellyfin", "onDownload": True, "onUpgrade": True, "onRename": True,
|
||||||
|
"onMovieDelete": True, "onMovieFileDelete": True, "onSeriesDelete": True, "onEpisodeFileDelete": True})
|
||||||
|
st, r = http("POST", u + "/notification", n, h)
|
||||||
|
log(name, "jellyfin connect", st, r if st >= 300 else "")
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------- Bazarr
|
# ---------------------------------------------------------------- Bazarr
|
||||||
def bazarr():
|
def bazarr():
|
||||||
import yaml # python3-yaml есть в Raspberry Pi OS
|
import yaml # python3-yaml есть в Raspberry Pi OS
|
||||||
@@ -333,7 +385,7 @@ def jellyseerr():
|
|||||||
log("seerr ok")
|
log("seerr ok")
|
||||||
|
|
||||||
|
|
||||||
STEPS = {"qbit": qbit, "jellyfin": jellyfin, "arr": arr, "prowlarr": prowlarr, "bazarr": bazarr, "seerr": jellyseerr}
|
STEPS = {"qbit": qbit, "jellyfin": jellyfin, "arr": arr, "prowlarr": prowlarr, "bazarr": bazarr, "connect": connect, "homepage": homepage, "seerr": jellyseerr}
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
for s in sys.argv[1:] or list(STEPS):
|
for s in sys.argv[1:] or list(STEPS):
|
||||||
|
|||||||
Reference in New Issue
Block a user