Ctrl K
ComunidadGuías…

README_UK.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
<img src="docs/icon.png" width="88" alt="">

# dsm-mini

[English](README.md) · [Русский](README_RU.md) · [Español](README_ES.md) · [Português](README_PT.md) · [Deutsch](README_DE.md) · [Français](README_FR.md) · [Italiano](README_IT.md) · [Türkçe](README_TR.md) · **Українська** · [Polski](README_PL.md)

[![Перевірки](https://github.com/alexlnos/dsm-mini/actions/workflows/ci.yml/badge.svg)](https://github.com/alexlnos/dsm-mini/actions/workflows/ci.yml)
[![Ліцензія MIT](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)

Telegram-бот з Mini App для керування домашнім NAS Synology: завантаження
Download Station і файли File Station просто з месенджера, без VPN і
вебінтерфейсу DSM.

Кинули magnet-посилання в чат — бот кнопками запитав, куди качати, і поставив у
чергу. Відкрили застосунок — видно, що завантажується, скільки лишилося, що
лежить на дисках і як почувається NAS.

<p align="center">
  <img src="docs/screenshots/uk-home.webp" width="19%" alt="Огляд NAS">
  <img src="docs/screenshots/uk-downloads.webp" width="19%" alt="Завантаження">
  <img src="docs/screenshots/uk-task.webp" width="19%" alt="Завдання">
  <img src="docs/screenshots/uk-files.webp" width="19%" alt="Файли">
  <img src="docs/screenshots/uk-storage.webp" width="19%" alt="Сховище">
</p>

> Працює: бот, Mini App і сповіщення. Потрібен DSM 7 або новіший — на DSM 6
> пакет не встановиться, і там його ніхто не перевіряв. Перевірено на DSM 7.2.2
> з Download Station 4.1.2 та File Station 1.4.4.

## Що воно вміє

**Завантаження**

- Список завдань: поступ, швидкість, час до кінця, сіди й піри
- Пауза, відновлення, видалення
- Додавання magnet-посиланням, прямим посиланням і файлом `.torrent`
- Вибір теки призначення з налаштовуваним списком швидкого доступу
- Вибір файлів усередині роздачі та їхнього пріоритету
- Повідомлення в чат, коли завдання завершилося або впало

**Файли**

- Огляд тек, попередній перегляд, вивантаження на NAS
- Перейменування, копіювання, перенесення, видалення

**Стан NAS**

- Навантаження процесора й пам'яті, час роботи, мережа
- Диски, пули та томи: температура, зайняте місце, здоров'я
- Віртуальні машини та контейнери: запуск і зупинка
- Журнал подій DSM

**Сповіщення та налаштування**

- Те, про що повідомляє сам DSM — радник із безпеки, диски, оновлення, — приходить у чат
- Вибір, що бот може надсилати: нічого, лише завантаження, усе
- Свій екран у головному меню DSM: там пакет налаштовується після встановлення і там само потім змінюється будь-яке налаштування, без перезапуску

**Мова**

Застосунок і бот говорять мовою, вибраною в Telegram: англійська, російська,
іспанська, португальська, німецька, французька, італійська, турецька,
українська, польська. Незнайома мова отримує англійську.

---

## Встановлення

Півгодини, і більшість піде на сертифікат, а не на сам сервіс. Потрібен NAS
Synology з DSM 7 і Download Station; більше нічого заздалегідь ставити не треба.

> **Публічна адреса потрібна лише для Mini App.** Telegram відкриває Mini App
> лише через `https://` зі справжнім сертифікатом — локальний `192.168.…` і
> самопідписаний не відкриються. Без адреси бот працює сам — посилання, файли
> `.torrent`, `/status` і сповіщення, — і відкривати NAS назовні не потрібно.
> Три способи отримати адресу — у кроці 4, два з них обходяться без прокидання
> портів на роутері.

**1. Створити бота.** [@BotFather](https://t.me/BotFather) → `/newbot` → ім'я
та логін, що закінчується на `bot`. У відповідь прийде токен; збережіть його,
це пароль від вашого бота.

**2. Дізнатися свій номер.** [@userinfobot](https://t.me/userinfobot) → Start.
Він відповість рядком `Id`.

**3. Завести користувача DSM для служби.** Панель керування → Користувач і група
→ Створити. Доступ лише до Download Station і File Station, без двоетапної
перевірки — одноразовий код нізвідки взяти у файлі налаштувань. Адміністратора
не давайте: служба вміє видаляти файли. Чи вистачає цьому обліковому запису
прав, покаже кнопка **Перевірити обліковий запис** у вікні DSM mini (крок 6):
вона входить від імені цього користувача й перелічує, що DSM йому дозволяє.

**4. Отримати адресу для Mini App** — або пропустіть цей крок, і бот працюватиме
сам. Адреса має відкриватися через `https://` на телефоні, де у вас Telegram.
Способів три. Перший — через DSM, із прокиданням портів на роутері; його можна
пропустити, якщо в NAS уже є домен із чинним сертифікатом:

- Панель керування → Зовнішній доступ → DDNS → Додати, постачальник
  `Synology` — вийде щось на кшталт `alex-nas.synology.me`.
- На роутері прокиньте на NAS порти **80** і **443**. Без 80 не випуститься
  сертифікат, без 443 не відкриється застосунок.
- Панель керування → Безпека → Сертифікат → Додати → від Let's Encrypt, на те
  саме ім'я.

Перевірте з телефона мобільним інтернетом:
`https://alex-nas.synology.me:5001` має відкрити DSM без попереджень.

Другий — **Cloudflare Tunnel**, без прокидання портів; потрібен домен, DNS якого
в Cloudflare. Створіть тунель у панелі Cloudflare, встановіть пакет **Cloudflare
Tunnel** із [SynoCommunity](https://synocommunity.com) з токеном цього тунелю й
додайте тунелю публічне ім'я — скажімо, `mini.example.com` — зі службою
`http://localhost:58080`.

Третій — **Tailscale**, лише для своїх пристроїв. Встановіть Tailscale на NAS і
на телефон, увімкніть сертифікати HTTPS у налаштуваннях DNS своєї мережі
Tailscale й виконайте на NAS `sudo tailscale serve --bg 58080`: він видасть
адресу на кшталт `https://nas.tail1234.ts.net`. Застосунок відкриватиметься,
поки телефон під'єднано до Tailscale.

**5. Встановити пакет.** Центр пакетів → Налаштування → Джерела пакетів →
Додати, ім'я `dsm-mini` і адреса за вашою архітектурою:

- Intel і AMD, більшість моделей: `https://alexlnos.github.io/dsm-mini/amd64.json`
- ARM, бюджетні моделі: `https://alexlnos.github.io/dsm-mini/arm64.json`

Далі Налаштування → Загальні → Рівень довіри → **Будь-який видавець**, і
встановіть **DSM mini — Telegram Mini App** з розділу **Спільнота**. Не
впевнені в архітектурі? Спробуйте `amd64`: невідповідний пакет просто не
встановиться.

Під час встановлення нічого не запитується. Або встановіть `.spk` з
[випусків](https://github.com/alexlnos/dsm-mini/releases) вручну, через Центр
пакетів → Ручне встановлення.

**6. Налаштувати.** Відкрийте **DSM mini** в головному меню DSM або натисніть
**Відкрити** в Центрі пакетів — він і сам підкаже це після встановлення.
Заповніть значення, зібрані на кроках вище, — вікно пояснить кожне, — а в
розділі **Доступ до Mini App** виберіть спосіб із кроку 4 або
**Лише бот, без Mini App**. Натисніть **Зберегти**, а потім **Запустити** вгорі
вікна. Статус там покаже, коли відповіли DSM і бот, а якщо не відповіли — що не
так.

Для першого способу правило зворотного проксі вікно створює саме: впишіть ім'я в
поле **Спрямувати ім'я до служби**. Вручну це Панель керування → Портал входу →
Додатково → Зворотний проксі → Створити. Джерело: `HTTPS`, ваше ім'я, порт
`443`. Призначення: `HTTP`, `localhost`, порт `58080`. З тунелем чи Tailscale
виберіть **Інший спосіб** і впишіть адресу, яку вони видали.

> Порт **80** для цього імені не проксіюйте: через нього DSM продовжує
> сертифікат, і перехоплення зламає продовження за три місяці.

**7. Перевірити.** Якщо адреса є, `https://ваша-адреса/healthz` у браузері має
відповісти `{"status":"ok"}`. Без підпису Telegram назовні нічого не віддається.

**8. Відкрити застосунок.** Знайдіть бота за логіном, натисніть Start — поряд із
полем введення з'явиться кнопка **Завантаження**. Надішліть йому будь-яке
magnet-посилання, він запропонує теки кнопками. Без адреси кнопки не буде —
посилання просто надсилайте боту в чат.

## Якщо щось пішло не так

| Що бачите | У чому річ | Що робити |
|---|---|---|
| Бот мовчить на `/start` | Бот вимкнений або не налаштований, чи хибний токен | Відкрийте **DSM mini** в головному меню DSM: статус угорі скаже, що саме, а **Запустити** увімкне бота |
| «Доступ до цього бота закрито» | Вашого ID немає в списку | Впишіть номер із кроку 2 в дозволені ID у вікні **DSM mini** |
| Кнопки застосунку немає | Публічна адреса порожня — тоді працює лише бот — або не `https://` | Вікно **DSM mini**, розділ **Доступ до Mini App** |
| Кнопка є, застосунок не відкривається | Не працює зворотний проксі або сертифікат | Відкрийте `https://ваша-адреса/healthz` у браузері |
| «Відкрийте застосунок через бота» | Застосунок відкрито прямим посиланням у браузері | Так і задумано: відкривайте з бота |
| «Доступ закрито: вашого Telegram ID…» | Сервіс вас не впізнав | У дозволених ID лише цифри, через кому |
| Вікно пише, що DSM не прийняв вхід | Пароль, 2FA або права користувача | Крок 3: пароль без описок, 2FA вимкнена, застосунки дозволені |
| Вікно пише, що Download Station не запущено | Її не встановлено або заборонено користувачеві | Центр пакетів і права з кроку 3 |
| Пакет зупиняється одразу після запуску | Його порт зайнятий чимось іншим — журнал так і скаже | Змініть `LISTEN_ADDR` у `config.env` через SSH (див. нижче) |

Перше, куди дивитися, — рядок стану вгорі вікна **DSM mini**: він каже, чи
відповіли DSM і Telegram, а якщо ні — чому. Подробиці — у журналі пакета,
`/var/packages/dsm-mini/var/dsm-mini.log`, він же відкривається з Центру
пакетів. Журнал ведеться англійською, вікно, інтерфейс і повідомлення бота —
вашою мовою.

### Змінити налаштування

**Відкрийте DSM mini в головному меню DSM** — там усі налаштування. Пароль і
токен лише на запис: залиште поле порожнім, і воно збереже попереднє. Збереження
застосовується одразу: служба сама перезапускається з новими налаштуваннями,
пакет перезапускати не треба.

Налаштування лежать на NAS в одному файлі
`/var/packages/dsm-mini/var/config.env` з правами `600`. Його можна виправити й
через SSH (Панель керування → Термінал і SNMP → увімкнути SSH), а потім
перезапустити пакет:

```bash
sudo sed -i "s|^TELEGRAM_BOT_TOKEN=.*|TELEGRAM_BOT_TOKEN='ваш-новий-токен'|" /var/packages/dsm-mini/var/config.env
sudo synopkg restart dsm-mini
```

Оновлення файл не чіпає, тому налаштування його переживають.

## Оновлення

Якщо додано джерело пакетів, Центр пакетів сам покаже оновлення. Без джерела —
завантажте свіжий `.spk` із
[випусків](https://github.com/alexlnos/dsm-mini/releases) і поставте поверх.

Налаштування й база в обох випадках залишаться: вони лежать у каталозі `var`
пакета, а оновлення його не чіпає.

## Де зберігаються дані

Усе в `/var/packages/dsm-mini/var/`:

- `config.env` — налаштування з вікна DSM mini, права `600`;
- `dsm-mini.db` — база SQLite: закріплені теки, мова й останні відомі статуси
  завдань, за якими сервіс розуміє, про що вже повідомляв;
- `dsm-mini.log` — журнал.

Оновлення пакета зберігає всі три. Видалення пакета — видаляє.

## Безпека

Сервіс виставлений в інтернет і вміє видаляти файли на NAS, тому:

- **Окремий користувач DSM**, а не адміністратор (крок 3).
- **Без двоетапної перевірки** в цього облікового запису: одноразовий код у
  конфігурації працювати не буде.
- **Дозволені ID — білий список.** Порожній список закриває доступ усім, а не
  відкриває.
- Кожен запит до `/api/` перевіряється двічі: підпис `initData` ключем від
  токена бота й ідентифікатор у списку дозволених. Підпис доводить лише те, що
  людина відкрила бота, — відкрити його може будь-хто.
- Назовні віддається загальна фраза, подробиці — в журнал: повідомлення про те,
  що саме не зійшлося в підписі, підказувало б, як його підібрати.
- Токен бота й пароль DSM живуть лише в `config.env` на самому NAS із правами
  `600` і в журнал не потрапляють: при відмові пишеться причина, але не
  значення.
- Служба слухає тільки `127.0.0.1` — тобто із самого NAS. Усе ззовні йде через
  те, що обслуговує публічну адресу, — зворотний проксі DSM, тунель чи
  Tailscale, — він же розбирає TLS. Без адреси ззовні до неї не доходить нічого.

## Розробка

```bash
cd web && npm install && npm run build   # Mini App потрапить у internal/web/dist
cd .. && go build ./cmd/dsm-mini         # бінарник із вбудованим застосунком
go test ./...
```

Фронтенд окремо, з автооновленням:

```bash
cd web && npm run dev    # ходить у бекенд на localhost:58080
```

Локальний запуск бекенда читає `config.env` зі `STATE_DIR`, як і пакет, а змінні
середовища доповнюють те, чого у файлі немає. Зручно тримати їх у файлі:

```bash
cp .env.example .env     # заповніть
set -a; . ./.env; set +a
go run ./cmd/dsm-mini
```

Зібраний інтерфейс лежить у репозиторії (`internal/web/dist`) — його забирає
`go:embed`. Після правок фронтенду перезберіть і закомітьте результат, інакше
перевірки не пройдуть.

Інтеграційні тести працюють проти справжнього NAS і типово пропускаються:

```bash
DSM_URL=https://192.168.1.10:5001 DSM_USER=... DSM_PASSWORD=... \
  DSM_INSECURE_TLS=true go test -tags=integration ./...
```

Тести, які змінюють стан NAS, потребують окремого дозволу:
`DSM_TEST_MUTATIONS=1`, а для файлових операцій ще й `DSM_TEST_FOLDER` — теку,
всередині якої можна створювати тимчасові файли. Усе створене вони прибирають за
собою.

Нова мова інтерфейсу — один файл словника з кожного боку:
`web/src/i18n/<код>.ts` та `internal/i18n/<код>.go`. Пропустити рядок не вийде:
на фронтенді за цим стежить тип, на сервері — тест.

Код, коментарі та журнал у проєкті — англійською; інші мови живуть лише у
словниках. Подробиці — у [CLAUDE.md](CLAUDE.md).

## Особливості Synology API

Web API Synology подекуди поводиться не так, як написано в документації: та сама
дія відповідає в трьох різних форматах, `limit = -1` кладе File Station, а `_sid`
під час вивантаження файлу треба передавати інакше, ніж усюди. Усе, що з'ясовано
на живому NAS, зібрано в [docs/synology-api.md](docs/synology-api.md).

## Ліцензія

[MIT](LICENSE)