Files
watchstate/config/config.php
Abdulmhsen B. A. A 2050676663 Made it so internal API requests wouldn't make it into access log.
There is a new ENV variable WS_API_LOG_INTERNAL to enable it if you desire, it's mostly helpful for development.
Internal API requests no longer require API key. Migrated system:env to use the API in effort to reduce code duplicating
There going to be more code cleaning later on once we migrate the majority of the code to the API.
2024-05-18 16:48:32 +03:00

305 lines
12 KiB
PHP

<?php
declare(strict_types=1);
use App\Backends\Emby\EmbyClient;
use App\Backends\Jellyfin\JellyfinClient;
use App\Backends\Plex\PlexClient;
use App\Commands\State\BackupCommand;
use App\Commands\State\ExportCommand;
use App\Commands\State\ImportCommand;
use App\Commands\State\ProgressCommand;
use App\Commands\State\PushCommand;
use App\Commands\State\RequestsCommand;
use App\Commands\System\IndexCommand;
use App\Commands\System\PruneCommand;
use App\Libs\Mappers\Import\MemoryMapper;
use Cron\CronExpression;
use Monolog\Level;
return (function () {
$inContainer = inContainer();
$config = [
'name' => 'WatchState',
'version' => '$(version_via_ci)',
'tz' => env('WS_TZ', env('TZ', 'UTC')),
'path' => fixPath(env('WS_DATA_PATH', fn() => $inContainer ? '/config' : __DIR__ . '/../var')),
'logs' => [
'context' => (bool)env('WS_LOGS_CONTEXT', false),
'prune' => [
'after' => env('WS_LOGS_PRUNE_AFTER', '-3 DAYS'),
],
],
'api' => [
'prefix' => '/v1/api',
'key' => env('WS_API_KEY', null),
'secure' => (bool)env('WS_SECURE_API_ENDPOINTS', false),
'pattern_match' => [
'backend' => '[a-zA-Z0-9_-]+',
],
'logInternal' => (bool)env('WS_API_LOG_INTERNAL', false),
],
'webui' => [
'enabled' => (bool)env('WEBUI_ENABLED', env('WS_WEBUI_ENABLED', true)),
'path' => fixPath(env('WS_WEBUI_PATH', __DIR__ . '/../public/exported')),
],
'database' => [
'version' => 'v01',
],
'library' => [
// -- this is used to segment backends requests into pages.
'segment' => (int)env('WS_LIBRARY_SEGMENT', 1_000),
],
'export' => [
// -- Trigger full export mode if changes exceed X number.
'threshold' => (int)env('WS_EXPORT_THRESHOLD', 1_000),
// -- Extra margin for marking item not found for backend in export mode. Default 3 days.
'not_found' => (int)env('WS_EXPORT_NOT_FOUND', 259_200),
],
'episodes' => [
'disable' => [
'guid' => (bool)env('WS_EPISODES_DISABLE_GUID', true),
]
],
'ignore' => [],
'trust' => [
'proxy' => (bool)env('WS_TRUST_PROXY', false),
'header' => (string)env('WS_TRUST_HEADER', 'X-Forwarded-For'),
],
];
$config['backends_file'] = fixPath(env('WS_BACKENDS_FILE', ag($config, 'path') . '/config/servers.yaml'));
date_default_timezone_set(ag($config, 'tz', 'UTC'));
$logDateFormat = makeDate()->format('Ymd');
$config['tmpDir'] = fixPath(env('WS_TMP_DIR', ag($config, 'path')));
$dbFile = ag($config, 'path') . '/db/watchstate_' . ag($config, 'database.version') . '.db';
$config['api']['logfile'] = ag($config, 'tmpDir') . '/logs/access.' . $logDateFormat . '.log';
$config['database'] += [
'file' => $dbFile,
'dsn' => 'sqlite:' . $dbFile,
'username' => null,
'password' => null,
'options' => [
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_STRINGIFY_FETCHES => false,
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
],
'exec' => [
'PRAGMA journal_mode=MEMORY',
'PRAGMA SYNCHRONOUS=OFF'
],
];
$config['webhook'] = [
'logfile' => ag($config, 'tmpDir') . '/logs/webhook.' . $logDateFormat . '.log',
'dumpRequest' => (bool)env('WS_WEBHOOK_DUMP_REQUEST', false),
'tokenLength' => (int)env('WS_WEBHOOK_TOKEN_LENGTH', 16),
'file_format' => (string)env('WS_WEBHOOK_LOG_FILE_FORMAT', 'webhook.{backend}.{event}.{id}.json'),
];
$config['mapper'] = [
'import' => [
'type' => MemoryMapper::class,
'opts' => [],
],
];
$config['http'] = [
'default' => [
'options' => [
'headers' => [
'User-Agent' => ag($config, 'name') . '/' . getAppVersion(),
],
'timeout' => 300.0,
'extra' => [
'curl' => [
CURLOPT_IPRESOLVE => CURL_IPRESOLVE_V4,
],
],
],
],
];
$config['debug'] = [
'profiler' => [
'options' => [
'save.handler' => 'file',
'save.handler.file' => [
'filename' => ag($config, 'tmpDir') . '/profiler/run.' . makeDate()->format('Ymd_His') . '.json'
],
],
],
];
$config['cache'] = [
'prefix' => env('WS_CACHE_PREFIX', null),
'url' => env('WS_CACHE_URL', 'redis://127.0.0.1:6379'),
'path' => env('WS_CACHE_PATH', fn() => ag($config, 'tmpDir') . '/cache'),
];
$config['logger'] = [
'file' => [
'type' => 'stream',
'enabled' => (bool)env('WS_LOGGER_FILE_ENABLE', true),
'level' => env('WS_LOGGER_FILE_LEVEL', Level::Error),
'filename' => ag($config, 'tmpDir') . '/logs/app.' . $logDateFormat . '.log',
],
'stderr' => [
'type' => 'stream',
'enabled' => 'cli' !== PHP_SAPI,
'level' => Level::Warning,
'filename' => 'php://stderr',
],
'console' => [
'type' => 'console',
'enabled' => 'cli' === PHP_SAPI,
// -- controllable by -vvv flag -v for NOTICE -vv for INFO -vvv for DEBUG.
'level' => Level::Warning,
],
'syslog' => [
'type' => 'syslog',
'docker' => false,
'facility' => env('WS_LOGGER_SYSLOG_FACILITY', LOG_USER),
'enabled' => (bool)env('WS_LOGGER_SYSLOG_ENABLED', !$inContainer),
'level' => env('WS_LOGGER_SYSLOG_LEVEL', Level::Error),
'name' => ag($config, 'name'),
],
];
$config['supported'] = [
'plex' => PlexClient::class,
'emby' => EmbyClient::class,
'jellyfin' => JellyfinClient::class,
];
$config['servers'] = [];
$config['php'] = [
'ini' => [
'disable_functions' => null,
'display_errors' => 0,
'error_log' => $inContainer ? '/proc/self/fd/2' : 'syslog',
'syslog.ident' => 'php-fpm',
'memory_limit' => '265M',
'pcre.jit' => 1,
'opcache.enable' => 1,
'opcache.memory_consumption' => 128,
'opcache.interned_strings_buffer' => 8,
'opcache.max_accelerated_files' => 10000,
'opcache.max_wasted_percentage' => 5,
'expose_php' => 0,
'date.timezone' => ag($config, 'tz', 'UTC'),
'mbstring.http_input' => ag($config, 'charset', 'UTF-8'),
'mbstring.http_output' => ag($config, 'charset', 'UTF-8'),
'mbstring.internal_encoding' => ag($config, 'charset', 'UTF-8'),
],
'fpm' => [
'global' => [
'daemonize' => 'no',
'error_log' => '/proc/self/fd/2',
'log_limit' => '8192',
],
'www' => [
'clear_env' => 'no',
'pm' => 'dynamic',
'pm.max_children' => 10,
'pm.start_servers' => 1,
'pm.min_spare_servers' => 1,
'pm.max_spare_servers' => 3,
'pm.max_requests' => 1000,
'pm.status_path' => '/status',
'ping.path' => '/ping',
'catch_workers_output' => 'yes',
'decorate_workers_output' => 'no',
],
],
];
$checkTaskTimer = function (string $timer, string $default): string {
try {
$isValid = (new CronExpression($timer))->getNextRunDate()->getTimestamp() >= 0;
return $isValid ? $timer : $default;
} catch (Throwable) {
return $default;
}
};
$config['tasks'] = [
'logfile' => ag($config, 'tmpDir') . '/logs/task.' . $logDateFormat . '.log',
'list' => [
ImportCommand::TASK_NAME => [
'command' => ImportCommand::ROUTE,
'name' => ImportCommand::TASK_NAME,
'info' => 'Import play state and metadata from backends.',
'enabled' => (bool)env('WS_CRON_IMPORT', false),
'timer' => $checkTaskTimer((string)env('WS_CRON_IMPORT_AT', '0 */1 * * *'), '0 */1 * * *'),
'args' => env('WS_CRON_IMPORT_ARGS', '-v'),
],
ExportCommand::TASK_NAME => [
'command' => ExportCommand::ROUTE,
'name' => ExportCommand::TASK_NAME,
'info' => 'Export play state to backends.',
'enabled' => (bool)env('WS_CRON_EXPORT', false),
'timer' => $checkTaskTimer((string)env('WS_CRON_EXPORT_AT', '30 */1 * * *'), '30 */1 * * *'),
'args' => env('WS_CRON_EXPORT_ARGS', '-v'),
],
PushCommand::TASK_NAME => [
'command' => PushCommand::ROUTE,
'name' => PushCommand::TASK_NAME,
'info' => 'Push Webhook play states to backends.',
'enabled' => (bool)env('WS_CRON_PUSH', true),
'timer' => $checkTaskTimer((string)env('WS_CRON_PUSH_AT', '*/10 * * * *'), '*/10 * * * *'),
'args' => env('WS_CRON_PUSH_ARGS', '-v'),
],
ProgressCommand::TASK_NAME => [
'command' => ProgressCommand::ROUTE,
'name' => ProgressCommand::TASK_NAME,
'info' => 'Push play progress to backends.',
'enabled' => (bool)env('WS_CRON_PROGRESS', false),
'timer' => $checkTaskTimer((string)env('WS_CRON_PROGRESS_AT', '*/45 * * * *'), '*/45 * * * *'),
'args' => env('WS_CRON_PROGRESS_ARGS', '-v'),
],
BackupCommand::TASK_NAME => [
'command' => BackupCommand::ROUTE,
'name' => BackupCommand::TASK_NAME,
'info' => 'Backup backends play states.',
'enabled' => (bool)env('WS_CRON_BACKUP', true),
'timer' => $checkTaskTimer((string)env('WS_CRON_BACKUP_AT', '0 6 */3 * *'), '0 6 */3 * *'),
'args' => env('WS_CRON_BACKUP_ARGS', '-v'),
],
PruneCommand::TASK_NAME => [
'command' => PruneCommand::ROUTE,
'name' => PruneCommand::TASK_NAME,
'info' => 'Delete old logs and backups.',
'enabled' => (bool)env('WS_CRON_PRUNE', true),
'timer' => $checkTaskTimer((string)env('WS_CRON_PRUNE_AT', '0 */12 * * *'), '0 */12 * * *'),
'args' => env('WS_CRON_PRUNE_ARGS', '-v'),
],
IndexCommand::TASK_NAME => [
'command' => IndexCommand::ROUTE,
'name' => IndexCommand::TASK_NAME,
'info' => 'Check database for optimal indexes.',
'enabled' => (bool)env('WS_CRON_INDEXES', true),
'timer' => $checkTaskTimer((string)env('WS_CRON_INDEXES_AT', '0 3 * * 3'), '0 3 * * 3'),
'args' => env('WS_CRON_INDEXES_ARGS', '-v'),
],
RequestsCommand::TASK_NAME => [
'command' => RequestsCommand::ROUTE,
'name' => RequestsCommand::TASK_NAME,
'info' => 'Process queued http requests.',
'enabled' => (bool)env('WS_CRON_REQUESTS', true),
'timer' => $checkTaskTimer((string)env('WS_CRON_REQUESTS_AT', '*/2 * * * *'), '*/2 * * * *'),
'args' => env('WS_CRON_REQUESTS_ARGS', '-v --no-stats'),
],
],
];
return $config;
})();