Point scripts at the shared host sections, and fix the two reasons those sections could never be found

This commit is contained in:
Gmer4Lfe
2026-08-06 23:16:28 -04:00
parent 4989486f45
commit bf7a2cc911
+59 -16
View File
@@ -63,24 +63,24 @@ const VV_SCRIPT_CONF_SECTIONS = [
'Docker_Essentials/downloaders_reset.sh' => ['Downloaders Reset', 'Downloaders'], 'Docker_Essentials/downloaders_reset.sh' => ['Downloaders Reset', 'Downloaders'],
// Watchdogs // Watchdogs
'Watchdogs/docker_watchdog.sh' => ['Docker Watchdog'], 'Watchdogs/docker_watchdog.sh' => ['Docker Watchdog'],
'Watchdogs/resource_watchdog.sh' => ['Pressure Thresholds'], 'Watchdogs/resource_watchdog.sh' => ['Pressure Thresholds', 'Downloaders', 'SABnzbd Throttle', 'qBittorrent Throttle'],
'Watchdogs/System/network_watchdog.sh' => ['Network Watchdog'], 'Watchdogs/System/network_watchdog.sh' => ['Network Watchdog'],
'Plugin/unraid/Watchdogs/System/webgui_watchdog.sh' => ['WebGUI Watchdog'], 'Plugin/unraid/Watchdogs/System/webgui_watchdog.sh' => ['WebGUI Watchdog'],
// Media // Media
'Media/media_cleaner.sh' => ['Media Cleaner'], 'Media/media_cleaner.sh' => ['Media Cleaner'],
'Media/media_shares_permissions.sh' => ['Media Permissions'], 'Media/media_shares_permissions.sh' => ['Media Permissions'],
// Arrs Stack // Arrs Stack
'Arrs_Stack/radarr_cleanup.sh' => ['Arr Cleanup'], 'Arrs_Stack/radarr_cleanup.sh' => ['Arr Cleanup', 'Radarr'],
'Arrs_Stack/lidarr_cleanup.sh' => ['Arr Cleanup'], 'Arrs_Stack/lidarr_cleanup.sh' => ['Arr Cleanup', 'Lidarr'],
'Arrs_Stack/sonarr_cleanup.sh' => ['Arr Cleanup'], 'Arrs_Stack/sonarr_cleanup.sh' => ['Arr Cleanup', 'Sonarr'],
// Monitors // Monitors
'Monitors/cert_monitor.sh' => ['Certificate Monitor'], 'Monitors/cert_monitor.sh' => ['Certificate Monitor'],
'Monitors/backup_verify.sh' => ['Backup Verify'], 'Monitors/backup_verify.sh' => ['Backup Verify'],
'Monitors/smart_health.sh' => ['SMART Health'], 'Monitors/smart_health.sh' => ['SMART Health'],
'Monitors/bandwidth_monitor.sh' => ['Bandwidth Monitor'], 'Monitors/bandwidth_monitor.sh' => ['Bandwidth Monitor'],
'Monitors/emby_session_report.sh' => ['Emby Session Report'], 'Monitors/emby_session_report.sh' => ['Emby Session Report', 'Emby'],
'Monitors/zfs_memory_snapshot.sh' => ['ZFS Report', 'ZFS Memory Snapshot'], 'Monitors/zfs_memory_snapshot.sh' => ['ZFS Report', 'ZFS Memory Snapshot'],
'Monitors/weekly_health_digest.sh' => ['Health Digest'], 'Monitors/weekly_health_digest.sh' => ['Health Digest', 'Certificate Monitor'],
'Monitors/system_tuning_monitor.sh' => ['System Tuning Monitor'], 'Monitors/system_tuning_monitor.sh' => ['System Tuning Monitor'],
// ── Added after auditing the conf against this map ──────────────────────────────────────── // ── Added after auditing the conf against this map ────────────────────────────────────────
// 99 named subsections existed; 35 were reachable. The rest were configured and documented in // 99 named subsections existed; 35 were reachable. The rest were configured and documented in
@@ -89,8 +89,8 @@ const VV_SCRIPT_CONF_SECTIONS = [
// unambiguously belong to one script are listed: a wrong mapping puts someone else's settings // unambiguously belong to one script are listed: a wrong mapping puts someone else's settings
// under a script and is worse than the gap it closes. // under a script and is worse than the gap it closes.
'Arrs_Stack/arr_download_orphan_cleaner.sh' => ['Download Orphan Cleaner (arr_download_orphan_cleaner.sh)'], 'Arrs_Stack/arr_download_orphan_cleaner.sh' => ['Download Orphan Cleaner (arr_download_orphan_cleaner.sh)'],
'Arrs_Stack/radarr_classification_scan.sh' => ['Arr Content Classification (radarr/sonarr_classification_scan.sh)'], 'Arrs_Stack/radarr_classification_scan.sh' => ['Arr Content Classification (radarr/sonarr_classification_scan.sh)', 'Radarr'],
'Arrs_Stack/sonarr_classification_scan.sh' => ['Arr Content Classification (radarr/sonarr_classification_scan.sh)'], 'Arrs_Stack/sonarr_classification_scan.sh' => ['Arr Content Classification (radarr/sonarr_classification_scan.sh)', 'Sonarr'],
'Arrs_Stack/arr_full_rescan.sh' => ['Arr Full Library Rescan'], 'Arrs_Stack/arr_full_rescan.sh' => ['Arr Full Library Rescan'],
'Arrs_Stack/arr_corruption_scan.sh' => ['Corruption Scan'], 'Arrs_Stack/arr_corruption_scan.sh' => ['Corruption Scan'],
'Arrs_Stack/arrs_failed_stalled_recovery.sh' => ['Arr Failed/Stalled Recovery', 'Arr Recovery Toggles'], 'Arrs_Stack/arrs_failed_stalled_recovery.sh' => ['Arr Failed/Stalled Recovery', 'Arr Recovery Toggles'],
@@ -99,7 +99,7 @@ const VV_SCRIPT_CONF_SECTIONS = [
'Fallback/fallback_test.sh' => ['Failover Test'], 'Fallback/fallback_test.sh' => ['Failover Test'],
'Rsync/rsync.sh' => ['Rsync Enable/Disable', 'Rsync Defaults', 'Rsync/rsync.sh' => ['Rsync Enable/Disable', 'Rsync Defaults',
'Rsync Profile System', 'Rsync Merge Auto-Promote'], 'Rsync Profile System', 'Rsync Merge Auto-Promote'],
'System_Essentials/server_reboot.sh' => ['Reboot'], 'System_Essentials/server_reboot.sh' => ['Reboot', 'Emby'],
'System_Essentials/clear_logs.sh' => ['Clear Logs'], 'System_Essentials/clear_logs.sh' => ['Clear Logs'],
'System_Essentials/inotify_tuning.sh' => ['inotify Tuning'], 'System_Essentials/inotify_tuning.sh' => ['inotify Tuning'],
'System_Essentials/docker_syslog_filter.sh' => ['Syslog Filter'], 'System_Essentials/docker_syslog_filter.sh' => ['Syslog Filter'],
@@ -107,9 +107,39 @@ const VV_SCRIPT_CONF_SECTIONS = [
'Plugin/unraid/System_Essentials/php_fpm_max_children.sh' => ['PHP-FPM'], 'Plugin/unraid/System_Essentials/php_fpm_max_children.sh' => ['PHP-FPM'],
'Watchdogs/stability_watchdog.sh' => ['Strike and Reboot Loop Settings', 'Watchdogs/stability_watchdog.sh' => ['Strike and Reboot Loop Settings',
'RAM Reboot Threshold', 'OOM Bypass Settings'], 'RAM Reboot Threshold', 'OOM Bypass Settings'],
'AI/ai_index.sh' => ['AI Retrieval Index', 'AI Master Switch'], 'AI/ai_index.sh' => ['AI Retrieval Index', 'AI Master Switch', 'Ollama'],
'AI/ai_query.sh' => ['AI Retrieval Index', 'AI Master Switch'], 'AI/ai_query.sh' => ['AI Retrieval Index', 'AI Master Switch', 'Ollama'],
'AI/ai_token_sync.sh' => ['AI Feature Toggles'], 'AI/ai_token_sync.sh' => ['AI Feature Toggles'],
// ── Shared host sections ──────────────────────────────────────────────────────────────────
// A script's settings are not only the ones named after it. Anything talking to Lidarr reads
// the host's Lidarr block; anything reading playback reads Emby. Those blocks are where the
// URL and API key actually live, so a script that could not work without them was showing a
// Config form that omitted the very settings most likely to be wrong.
//
// Several scripts pointing at one section is intended, not duplication — the arr cleanups
// already shared 'Arr Cleanup' this way. Writes are confined to the parsed line range, so a
// section edited from two places still edits the same lines.
'Arrs_Stack/lidarr_missing_art.sh' => ['Lidarr'],
'Arrs_Stack/lidarr_release_fixer.sh' => ['Lidarr'],
'Arrs_Stack/lidarr_duplicate_artist_cleanup.sh' => ['Lidarr'],
'Arrs_Stack/playback_aware_lidarr_discovery.sh' => ['Lidarr', 'Emby'],
'Arrs_Stack/playback_aware_radarr_discovery.sh' => ['Radarr', 'Emby'],
'Arrs_Stack/playback_aware_sonarr_discovery.sh' => ['Sonarr', 'Emby'],
'Arrs_Stack/radarr_tmdb_removed.sh' => ['Radarr'],
'Arrs_Stack/sonarr_tvdb_removed.sh' => ['Sonarr'],
'Tools/emby_to_lidarr_sync.sh' => ['Emby', 'Lidarr'],
'Tools/emby_to_radarr_sync.sh' => ['Emby', 'Radarr'],
'Tools/emby_to_sonarr_sync.sh' => ['Emby', 'Sonarr'],
'Tools/emby_database_repair.sh' => ['Emby'],
'Tools/bulk_permissions_repair.sh' => ['Media Permissions'],
'Tools/trailer_folder_migration.sh' => ['Media Permissions'],
'Transcodes/transcode_manager.sh' => ['Transcode Manager', 'Transcode Server Array'],
// fallback.sh owns the whole failover surface: which tiers it covers, how long it waits, what
// it does to DDNS, and what it hands back. All four sections are its configuration.
'Fallback/fallback.sh' => ['Fallback Tiers — What HOSTN Wants Covered When Down',
'Tier Delays — HOSTN Outage Timers',
'Internet Loss', 'DDNS',
'Play State Sync — Handback'],
]; ];
function vv_conf_has_sections(string $id): bool { function vv_conf_has_sections(string $id): bool {
@@ -122,13 +152,24 @@ function vv_conf_has_sections(string $id): bool {
function vv_conf_parse_subsection(string $raw, string $subName, string $filename): ?array { function vv_conf_parse_subsection(string $raw, string $subName, string $filename): ?array {
$lines = explode("\n", $raw); $lines = explode("\n", $raw);
$n = count($lines); $n = count($lines);
$needle = mb_strtolower(trim(preg_replace('/\s+/', ' ', $subName))); // Host slot normalised on both sides. Section titles carry the host they belong to — the
// template ships "Tier Delays — HOSTN Outage Timers" and conf_upgrade substitutes it to HOST1
// or HOST2 per machine — so a literal name in the map can only ever match one host, and on
// the other it silently finds nothing. Folding HOST<n> back to HOSTN makes one entry correct
// everywhere, which matters because this map is shared code and the conf files are not.
$slot = fn(string $s): string
=> preg_replace('/\bhost\d+\b/', 'hostn', mb_strtolower(trim(preg_replace('/\s+/', ' ', $s))));
$needle = $slot($subName);
$start = -1; $start = -1;
// /u is load-bearing, not tidiness. Without it the character class matches BYTES, and an
// em-dash (E2 80 94) is built entirely from bytes that also appear in ━ and ─. So a name
// containing one terminated early: "Tier Delays — HOSTN Outage Timers" captured as "Tier
// Delays", matched nothing, and every section with a dash in its title was unreachable —
// silently, because an unfound section is defined to return no fields.
for ($i = 0; $i < $n; $i++) { for ($i = 0; $i < $n; $i++) {
if (!preg_match('/^#\s*[━─]{2,}\s+([A-Za-z].+?)\s+[━─]{2,}/', $lines[$i], $m)) continue; if (!preg_match('/^#\s*[━─]{2,}\s+([A-Za-z].+?)\s+[━─]{2,}/u', $lines[$i], $m)) continue;
$t = mb_strtolower(trim(preg_replace('/\s+/', ' ', $m[1]))); if ($slot($m[1]) === $needle) { $start = $i + 1; break; }
if ($t === $needle) { $start = $i + 1; break; }
} }
if ($start === -1) return null; if ($start === -1) return null;
@@ -230,7 +271,9 @@ function vv_conf_all_groups(string $filename): array {
$headers = []; $headers = [];
for ($i = 0; $i < $n; $i++) { for ($i = 0; $i < $n; $i++) {
if (preg_match('/^#\s*[━─]{2,}\s+([A-Za-z].+?)\s+[━─]{2,}/', $lines[$i], $m)) { // /u for the same reason as the locator above: without it a name containing an em-dash is
// truncated at the dash, and the full-settings view labels the group with half its title.
if (preg_match('/^#\s*[━─]{2,}\s+([A-Za-z].+?)\s+[━─]{2,}/u', $lines[$i], $m)) {
$headers[] = ['name' => trim(preg_replace('/\s+/', ' ', $m[1])), 'line' => $i]; $headers[] = ['name' => trim(preg_replace('/\s+/', ' ', $m[1])), 'line' => $i];
} }
} }