# Watch Folder — Автоматический импорт медиа

Watch Folder — система автоматического импорта контента. Она мониторит локальные директории (или rclone-ремоуты) на наличие новых видеофайлов, парсит имена для извлечения метаданных (название, год, сезон, эпизод), запрашивает TMDB для получения обложек и описаний, и создаёт записи фильмов/сериалов в базе данных — без ручного вмешательства.

---

## Как это работает

```
┌──────────────────┐     ┌──────────────────┐     ┌──────────────────┐
│  Watch Folder    │────▶│   WatchCron       │────▶│  WatchItem       │
│  (директория     │     │  сканирует новые  │     │  парсит имя      │
│   на диске /     │     │  файлы, фильтрует │     │  запрашивает TMDB│
│   rclone)        │     │  уже импортирован.│     │  создаёт запись  │
└──────────────────┘     └──────────────────┘     └──────────────────┘
                                                          │
                                                          ▼
                                                   ┌──────────────────┐
                                                   │  Обновление      │
                                                   │  букетов         │
                                                   │  (авто-привязка) │
                                                   └──────────────────┘
```

### Пошагово

1. **Админ создаёт Watch Folder** в admin-панели (Watch Folder → Add) или через API (`create_watch_folder`). Конфигурация включает: путь к директории, тип контента (movie/series), целевую категорию, букеты, парсер и назначенный сервер.
2. **Крон `cron:watch`** запускается периодически (интервал контролируется `scan_offset` — секунды между сканами). Он выбирает из `watch_folders` активные папки, у которых `last_run` превысил offset.
3. **Обнаружение файлов** — крон использует `find` для локальных директорий или `rclone lsjson` для облачных/удалённых хранилищ. Файлы фильтруются по разрешённым расширениям (по умолчанию: `mp4, mkv, avi, mpg, flv, 3gp, m4v, wmv, mov, ts`). Файлы, уже присутствующие в `streams.stream_source`, пропускаются.
4. **Проверка стабильности** — файлы, изменённые менее 30 секунд назад, пропускаются (чтобы не импортировать частично загруженные файлы).
5. **Параллельная обработка** — каждый новый файл отправляется в команду `watch_item` (через `shell_exec`), до `thread_count` элементов запускается параллельно через `Multithread`.
6. **WatchItem** парсит имя файла с помощью PTN или guessit (см. документацию парсеров ниже), запрашивает метаданные через TMDB API и вставляет запись в `streams` (для фильмов) или `streams_series` + `streams_episodes` (для сериалов).
7. **Привязка к букетам** — импортированные элементы автоматически добавляются в заданные букеты.

---

## Конфигурация

### Настройки Watch Folder (для каждой папки)

| Настройка | Описание |
|-----------|----------|
| `directory` | Локальный путь для сканирования (напр., `/mnt/media/movies/`) |
| `rclone_dir` | Путь rclone-ремоута (альтернатива локальной директории) |
| `type` | Тип контента: `movie` или `series` |
| `server_id` | Сервер, на котором запускается сканирование |
| `category_id` | Целевая категория для импортированного контента |
| `bouquets` | Автоматическая привязка к этим букетам |
| `fb_category_id` | Фолбэк-категория (если маппинг жанров TMDB не сработает) |
| `fb_bouquets` | Фолбэк-букеты |
| `allowed_extensions` | Расширения файлов для сканирования (пусто = список по умолчанию) |
| `language` | Предпочитаемый язык TMDB для метаданных |
| `active` | Включить/выключить эту папку |

### Булевые опции

| Опция | Описание |
|-------|----------|
| `disable_tmdb` | Пропустить запрос к TMDB — импортировать только с parsed-названием |
| `ignore_no_match` | Импортировать, даже если TMDB не вернул результат |
| `auto_subtitles` | Автоматически обнаруживать `.srt`, `.sub`, `.sbv` рядом с видео |
| `fallback_title` | Использовать имя папки как название, если парсер не извлёк его |
| `read_native` | Читать оригинальное название из TMDB |
| `movie_symlink` | Создавать симлинки вместо ссылки на оригинальный путь |
| `auto_encode` | Автоматически перекодировать импортированный контент |
| `auto_upgrade` | Заменить существующую версию худшего качества при совпадении TMDB ID |
| `duplicate_tmdb` | Разрешить множественный импорт с одинаковым TMDB ID |
| `ffprobe_input` | Запустить ffprobe на файле для извлечения метаданных кодека |
| `extract_metadata` | Извлечь дополнительные метаданные из файла |

### Глобальные настройки

| Настройка | Где | Описание |
|-----------|-----|----------|
| `tmdb_api_key` | Админка → Настройки | **Обязательно** — ключ TMDB API. Без него Watch не запустится |
| `fallback_parser` | Админка → Настройки | Парсер, используемый при отказе основного |
| `alternative_titles` | Админка → Настройки | Искать альтернативные названия в TMDB |
| `max_genres` | Админка → Настройки | Максимум жанров для привязки к элементу |

---

## Админ-панель и API

### Страницы в админ-панели

| Страница | Описание |
|----------|----------|
| Watch Folder → List | Список всех настроенных папок со статусом |
| Watch Folder → Add | Создание/редактирование watch folder |
| Watch Folder → Settings | Глобальные настройки (парсер, TMDB) |
| Watch Folder → Logs | Просмотр логов сканирования и ошибок |

### API-действия

| Действие | Описание |
|----------|----------|
| `get_watch_folders` | Список всех watch folders |
| `get_watch_folder` | Получить папку по ID |
| `create_watch_folder` | Создать новую watch folder |
| `edit_watch_folder` | Обновить существующую |
| `delete_watch_folder` | Удалить watch folder |
| `reload_watch_folder` | Принудительное пересканирование |
| `enable_watch` | Включить все watch folders |
| `disable_watch` | Выключить все watch folders |
| `kill_watch` | Убить все запущенные watch-процессы |

### CLI

```bash
# Обычный запуск крона (обычно запускается автоматически)
sudo -u xc_vm /home/xc_vm/console.php cron:watch

# Принудительное сканирование конкретной папки (по ID)
sudo -u xc_vm /home/xc_vm/console.php cron:watch 5
```

---

## Парсеры

Доступны два парсера имён файлов. Парсер извлекает структурированные метаданные (название, год, сезон, эпизод, разрешение, кодек) из имени видеофайла.

### Выбор парсера

| Парсер | Лучше подходит для |
|--------|-------------------|
| **PTN** | Простые имена с пробелами: `San Andreas 2015 720p.mkv` |
| **guessit** | Имена с точками: `The.Matrix.1999.1080p.BluRay.mkv` |

Основной парсер задаётся для каждой watch folder. Глобальная настройка `fallback_parser` используется, когда основной парсер не находит совпадение.

---

## 1️⃣ PTN Parser

PTN parser поддерживает разбор файлов фильмов и сериалов с типичными именами.

### Фильмы

| Пример имени файла | Разбор |
|------------------|-------|
| `San Andreas 2015 720p WEB-DL x264 AAC-JYK.mkv` | Название: *San Andreas*, Год: 2015, Разрешение: 720p, Видео: x264, Аудио: AAC, Группа: JYK |
| `The Martian 2015 540p HDRip KORSUB x264 AAC2 0-FGT.mp4` | Название: *The Martian*, Год: 2015, Разрешение: 540p, Видео: x264, Аудио: AAC2.0, Группа: FGT |

### Сериалы

| Пример имени файла | Разбор |
|------------------|-------|
| `friends.s02e01.720p.bluray-sujaidr.mkv` | Название: *Friends*, Сезон: 2, Эпизод: 1, Разрешение: 720p, Формат: bluray, Группа: sujaidr |
| `Mr Robot S01E05 HDTV x264-KILLERS[ettv].mp4` | Название: *Mr Robot*, Сезон: 1, Эпизод: 5, Формат: HDTV, Видео: x264, Группа: KILLERS |

---

## 2️⃣ guessit Parser

Guessit поддерживает сложные форматы, включая точечные разделители и мультиязычные названия.

### Фильмы

| Пример имени файла | Разбор |
|------------------|-------|
| `The.Matrix.1999.1080p.BluRay.x264.DTS-FGT.mkv` | Название: *The Matrix*, Год: 1999, Разрешение: 1080p, Видео: x264, Аудио: DTS, Группа: FGT |
| `Inception.2010.720p.BRRip.x264.AAC-ETRG.mkv` | Название: *Inception*, Год: 2010, Разрешение: 720p, Видео: x264, Аудио: AAC, Группа: ETRG |

### Сериалы

| Пример имени файла | Разбор |
|------------------|-------|
| `Breaking.Bad.S03E07.720p.BluRay.x264-REWARD.mkv` | Название: *Breaking Bad*, Сезон: 3, Эпизод: 7, Разрешение: 720p, Видео: x264, Группа: REWARD |
| `Game.of.Thrones.S05E09.1080p.WEB-DL.DD5.1.H.264-NTb.mkv` | Название: *Game of Thrones*, Сезон: 5, Эпизод: 9, Разрешение: 1080p, Видео: H.264, Аудио: DD5.1, Группа: NTb |

---

### Fallback to Folder Name

Если имя файла не содержит название сериала, включите опцию **Fallback to Folder Name**:

| Пример пути | Разбор |
|-------------|-------|
| `/path/to/Show Name/S01E01 720p WEB-DL.mkv` | Название: *Show Name*, Сезон: 1, Эпизод: 1 |
| `/path/to/Show.Name/S01E01.720p.WEB-DL.mkv` | Название: *Show Name*, Сезон: 1, Эпизод: 1 |

#### Разделение по папкам с сезонами

Если нужно разложить эпизоды по папкам:

| Пример пути | Разбор |
|-------------|-------|
| `/path/to/Show Name/Season 01/Show Name S01E01 720p WEB-DL.mkv` | Название: *Show Name*, Сезон: 1, Эпизод: 1 |
| `/path/to/Show.Name/Season.01/Show.Name.S01E01.720p.WEB-DL.mkv` | Название: *Show Name*, Сезон: 1, Эпизод: 1 |

---

### RTL-языки

Для сериалов на RTL-языках:

- Имя файла **не должно содержать название сериала**  
- Включите опцию **Fallback to Folder Name**  

| Пример пути | Разбор |
|-------------|-------|
| `/path/to/Show Name/S01E01 (year).mp4` | Название: *Show Name*, Сезон: 1, Эпизод: 1, Год: `year` |
| `/path/to/Show Name/Season 01/S01E01 (year).mp4` | Название: *Season 01*, Сезон: 1, Эпизод: 1, Год: `year` |

> ⚠️ Важно: для RTL-языков название сериала берется только из имени папки.

---

### Резюме

- **PTN Parser** — простые имена файлов, локальные форматы  
- **guessit Parser** — поддержка точечных разделителей, мультиязычных названий, Fallback к имени папки  
- **RTL-языки** — обязательно использовать Fallback к имени папки  
- **Разделение по сезонам** — название сериала должно присутствовать в имени файла  

---

💡 **Совет:** используйте однородные имена файлов и папок для корректного парсинга и автоматической сортировки сериалов по сезонам.
