mirror of
https://github.com/Vateron-Media/XC_VM.git
synced 2026-10-23 12:03:09 +02:00
201 lines
12 KiB
Markdown
201 lines
12 KiB
Markdown
# Модель обработки ошибок
|
|
|
|
В XC_VM обработка ошибок разделена на два уровня: **коды ошибок** (что пошло не так) и **обработчики** (как это отображается клиенту).
|
|
|
|
---
|
|
|
|
## Обзор архитектуры
|
|
|
|
```
|
|
Код ошибки (строка)
|
|
│
|
|
▼
|
|
generateError($code)
|
|
│
|
|
├─ debug_show_errors = true → стилизованная HTML-страница с кодом и описанием
|
|
└─ production → generate404() (имитация nginx 404)
|
|
```
|
|
|
|
---
|
|
|
|
## Коды ошибок
|
|
|
|
Все коды хранятся в `src/core/Error/ErrorCodes.php` в массиве `$rErrorCodes`.
|
|
|
|
Код — это строковый ключ (`'INVALID_CREDENTIALS'`), значение — описание на английском языке.
|
|
|
|
### Полный список кодов
|
|
|
|
| Код | Описание |
|
|
| -------------------------- | ----------------------------------------------------- |
|
|
| `API_IP_NOT_ALLOWED` | IP не имеет доступа к API |
|
|
| `ARCHIVE_DOESNT_EXIST` | Файлы архива для данного стрима отсутствуют |
|
|
| `ASN_BLOCKED` | ASN заблокирован |
|
|
| `BANNED` | Линия заблокирована |
|
|
| `BLOCKED_USER_AGENT` | User-agent заблокирован |
|
|
| `CACHE_INCOMPLETE` | Кеш ещё генерируется |
|
|
| `DEVICE_NOT_ALLOWED` | MAG/Enigma устройства не имеют доступа |
|
|
| `DISABLED` | Линия отключена |
|
|
| `DOWNLOAD_LIMIT_REACHED` | Достигнут лимит одновременных загрузок |
|
|
| `E2_DEVICE_LOCK_FAILED` | Проверка блокировки устройства не пройдена |
|
|
| `E2_DISABLED` | Устройство отключено |
|
|
| `E2_NO_TOKEN` | Токен не указан |
|
|
| `E2_TOKEN_DOESNT_MATCH` | Токен не совпадает с записями |
|
|
| `E2_WATCHDOG_TIMEOUT` | Превышен лимит времени |
|
|
| `EMPTY_USER_AGENT` | Пустые user-agent запрещены |
|
|
| `EPG_DISABLED` | EPG отключён |
|
|
| `EPG_FILE_MISSING` | Кешированные файлы EPG отсутствуют |
|
|
| `EXPIRED` | Линия истекла |
|
|
| `FORCED_COUNTRY_INVALID` | Страна не соответствует принудительной |
|
|
| `GENERATE_PLAYLIST_FAILED` | Не удалось сгенерировать плейлист |
|
|
| `HLS_DISABLED` | HLS отключён |
|
|
| `HOSTING_DETECT` | Обнаружен хостинг-сервер |
|
|
| `INVALID_API_PASSWORD` | Неверный пароль API |
|
|
| `INVALID_CREDENTIALS` | Неверный логин или пароль |
|
|
| `INVALID_HOST` | Домен не распознан |
|
|
| `INVALID_STREAM_ID` | Стрим с таким ID не существует |
|
|
| `INVALID_TYPE_TOKEN` | Токен нельзя использовать для этого типа стрима |
|
|
| `IP_BLOCKED` | IP заблокирован |
|
|
| `IP_MISMATCH` | Текущий IP не совпадает с IP первого подключения |
|
|
| `ISP_BLOCKED` | ISP заблокирован |
|
|
| `LB_TOKEN_INVALID` | AES-токен не может быть расшифрован |
|
|
| `LEGACY_EPG_DISABLED` | Доступ к legacy epg.php отключён |
|
|
| `LEGACY_GET_DISABLED` | Доступ к legacy get.php отключён |
|
|
| `LEGACY_PANEL_API_DISABLED`| Доступ к legacy panel_api.php отключён |
|
|
| `LINE_CREATE_FAIL` | Не удалось добавить линию в базу данных |
|
|
| `NO_CREDENTIALS` | Учётные данные не указаны |
|
|
| `NO_SERVERS_AVAILABLE` | Нет доступных серверов для этого стрима |
|
|
| `NO_TIMESTAMP` | Временная метка архива не указана |
|
|
| `NO_TOKEN_SPECIFIED` | AES-токен не указан |
|
|
| `NOT_ENIGMA_DEVICE` | Линия не является Enigma-устройством |
|
|
| `NOT_IN_ALLOWED_COUNTRY` | Страна не в списке разрешённых |
|
|
| `NOT_IN_ALLOWED_IPS` | IP не в списке разрешённых |
|
|
| `NOT_IN_ALLOWED_UAS` | User-agent не в списке разрешённых |
|
|
| `NOT_IN_BOUQUET` | Линия не имеет доступа к этому стриму |
|
|
| `PLAYER_API_DISABLED` | Player API отключён |
|
|
| `PROXY_ACCESS_DENIED` | Прямой доступ к стриму запрещён при включённом прокси |
|
|
| `PROXY_DETECT` | Обнаружен прокси |
|
|
| `PROXY_NO_API_ACCESS` | Доступ к API через прокси запрещён |
|
|
| `RESTREAM_DETECT` | Обнаружено ретрансляция |
|
|
| `STALKER_CHANNEL_MISMATCH` | ID стрима не совпадает со stalker-токеном |
|
|
| `STALKER_DECRYPT_FAILED` | Не удалось расшифровать stalker-токен |
|
|
| `STALKER_INVALID_KEY` | Неверный stalker-ключ |
|
|
| `STALKER_IP_MISMATCH` | IP не совпадает со stalker-токеном |
|
|
| `STALKER_KEY_EXPIRED` | Stalker-токен истёк |
|
|
| `STREAM_OFFLINE` | Стрим сейчас недоступен |
|
|
| `SUBTITLE_DOESNT_EXIST` | Файл субтитров не существует |
|
|
| `THUMBNAIL_DOESNT_EXIST` | Файл превью не существует |
|
|
| `THUMBNAILS_NOT_ENABLED` | Превью не включено для этого стрима |
|
|
| `TOKEN_ERROR` | AES-токен содержит неполные данные |
|
|
| `TOKEN_EXPIRED` | AES-токен истёк |
|
|
| `TS_DISABLED` | MPEG-TS отключён |
|
|
| `USER_ALREADY_CONNECTED` | Линия уже подключена с другого IP |
|
|
| `USER_DISALLOW_EXT` | Расширение не входит в список разрешённых |
|
|
| `VOD_DOESNT_EXIST` | VOD-файл не существует |
|
|
| `WAIT_TIME_EXPIRED` | Таймаут запуска стрима истёк |
|
|
|
|
---
|
|
|
|
## Функции обработки
|
|
|
|
Определены в `src/core/Error/ErrorHandler.php`.
|
|
|
|
### `generateError(string $code, bool $kill = true, ?int $httpCode = null)`
|
|
|
|
Отображает ошибку клиенту.
|
|
|
|
**Логика:**
|
|
|
|
```
|
|
если debug_show_errors = true
|
|
→ HTML-страница с кодом и описанием ошибки
|
|
иначе
|
|
если $httpCode задан → http_response_code($httpCode) + exit
|
|
иначе → generate404()
|
|
```
|
|
|
|
**Параметры:**
|
|
|
|
| Параметр | Тип | Умолчание | Описание |
|
|
| ---------- | --------- | --------- | ---------------------------------------------------- |
|
|
| `$rError` | `string` | — | Код ошибки из `$rErrorCodes` |
|
|
| `$rKill` | `bool` | `true` | Завершить выполнение после вывода |
|
|
| `$rCode` | `int\|null` | `null` | HTTP-код ответа (если `null` — используется 404) |
|
|
|
|
**Примеры:**
|
|
|
|
```php
|
|
// Стандартная ошибка — завершить скрипт с 404
|
|
generateError('INVALID_CREDENTIALS');
|
|
|
|
// Вернуть 403 без завершения скрипта
|
|
generateError('API_IP_NOT_ALLOWED', false, 403);
|
|
|
|
// Только показать ошибку, выполнение продолжается
|
|
generateError('STREAM_OFFLINE', false);
|
|
```
|
|
|
|
---
|
|
|
|
### `generate404(bool $kill = true)`
|
|
|
|
Отдаёт стандартную страницу `404 Not Found`, стилизованную под nginx.
|
|
|
|
```php
|
|
generate404(); // 404 + exit()
|
|
generate404(false); // 404, продолжить выполнение
|
|
```
|
|
|
|
> Используется автоматически внутри `generateError()` в production-режиме.
|
|
|
|
---
|
|
|
|
## Режимы отображения
|
|
|
|
### Production (по умолчанию)
|
|
|
|
Клиент получает стандартный nginx 404. Реальная причина ошибки скрыта.
|
|
|
|
```
|
|
HTTP/1.1 404 Not Found
|
|
<html><head><title>404 Not Found</title></head>
|
|
<body><center><h1>404 Not Found</h1></center><hr><center>nginx</center></body>
|
|
</html>
|
|
```
|
|
|
|
### Debug-режим
|
|
|
|
Включается настройкой `debug_show_errors = true` в конфигурации.
|
|
Отображает код ошибки и его описание из `$rErrorCodes`.
|
|
|
|
> ⚠️ Никогда не включайте debug-режим на production-серверах — это раскрывает внутреннюю логику системы клиентам.
|
|
|
|
---
|
|
|
|
## Добавление нового кода ошибки
|
|
|
|
Добавьте запись в массив `$rErrorCodes` в файле `src/core/Error/ErrorCodes.php`:
|
|
|
|
```php
|
|
'MY_NEW_ERROR' => 'Human-readable description of the error.',
|
|
```
|
|
|
|
Затем используйте код там, где нужно:
|
|
|
|
```php
|
|
generateError('MY_NEW_ERROR');
|
|
```
|
|
|
|
Описание должно быть на **английском языке** — это требование существующего формата.
|
|
|
|
---
|
|
|
|
## Связанные файлы
|
|
|
|
| Файл | Назначение |
|
|
| --------------------------------- | --------------------------------------- |
|
|
| `src/core/Error/ErrorCodes.php` | Реестр всех кодов ошибок |
|
|
| `src/core/Error/ErrorHandler.php` | `generateError()`, `generate404()` |
|
|
| `src/bootstrap.php` | Загружает ErrorHandler через constants |
|
|
| `src/www/constants.php` | Точка подключения Error-модуля |
|