diff --git a/aw-server/apply_webui_ru_patch.sh b/aw-server/apply_webui_ru_patch.sh index 2d37b7b..1b7c240 100755 --- a/aw-server/apply_webui_ru_patch.sh +++ b/aw-server/apply_webui_ru_patch.sh @@ -23,6 +23,8 @@ TRENDS_NEEDLE='this.activityStore.query_category_time_by_period(r)' TRENDS_REPLACEMENT='this.activityStore.ensure_loaded(r)' TIMESPIRAL_NEEDLE='start:new Date("2022-08-08")' TIMESPIRAL_REPLACEMENT='start:new Date(Date.now()-12*36e5)' +CATEGORY_HELPER_NEEDLE='hostname:t.hostnameChoices[0]' +CATEGORY_HELPER_REPLACEMENT='hostname:t.hostnameChoices.filter((function(t){return"unknown"!==t}))[0]||t.hostnameChoices[0]' [[ -f "$PATCH_JS_SRC" ]] || { echo "missing $PATCH_JS_SRC" >&2; exit 1; } [[ -f "$SW_CLEANUP_SRC" ]] || { echo "missing $SW_CLEANUP_SRC" >&2; exit 1; } @@ -85,4 +87,25 @@ else echo "Timespiral hotfix skipped: chunk not found" fi +category_helper_chunk="$(grep -Rsl "$CATEGORY_HELPER_NEEDLE" "$WEBUI_DIR/js"/*.js 2>/dev/null | head -n 1 || true)" +if [[ -n "$category_helper_chunk" ]]; then + cp "$category_helper_chunk" "$category_helper_chunk.bak.$TS" + python3 - "$category_helper_chunk" "$CATEGORY_HELPER_NEEDLE" "$CATEGORY_HELPER_REPLACEMENT" <<'PY' +from pathlib import Path +import sys + +path = Path(sys.argv[1]) +old = sys.argv[2] +new = sys.argv[3] +content = path.read_text() +if old in content: + path.write_text(content.replace(old, new, 1)) + print(f"Category helper host hotfix applied to {path}") +else: + print(f"Category helper host hotfix already present in {path}") +PY +else + echo "Category helper host hotfix skipped: chunk not found" +fi + echo "RU patch applied to $WEBUI_DIR (ru-patch-v5.js?v=$patch_hash)" diff --git a/aw-server/aw-ru-patch.js b/aw-server/aw-ru-patch.js index 1052651..363ae10 100755 --- a/aw-server/aw-ru-patch.js +++ b/aw-server/aw-ru-patch.js @@ -1,6 +1,6 @@ (function () { - window.__awRuPatchVersion = "template-v10-pve-detmir-audit-stable"; - document.documentElement.setAttribute("data-aw-ru-patch", "template-v10-pve-detmir-audit-stable"); + window.__awRuPatchVersion = "template-v11-category-builder-host-fix"; + document.documentElement.setAttribute("data-aw-ru-patch", "template-v11-category-builder-host-fix"); const exact = new Map([ ["ActivityWatch", "АктивВотч"], @@ -1419,6 +1419,7 @@ let trendsRedirectInFlight = false; let settingsHostFetchInFlight = false; let applyPatchScheduled = false; + let networkPatchesInstalled = false; function getTrendsHostFromSettings(settings) { if (!settings || typeof settings !== "object") return ""; @@ -1479,13 +1480,108 @@ }); } + function getPreferredWindowHostFromBuckets() { + const state = getHostGroupsState(); + const rawBuckets = state && state.buckets ? state.buckets : {}; + const settingsHost = normalizeText(window.__awRuPatchSettingsHost || ""); + const bucketIds = Array.isArray(rawBuckets) + ? rawBuckets.map(function (item) { return item && item.id ? String(item.id) : ""; }) + : Object.keys(rawBuckets || {}); + const hosts = bucketIds + .filter(function (bucketId) { return /^aw-watcher-window_/i.test(bucketId); }) + .map(function (bucketId) { return bucketId.replace(/^aw-watcher-window_/i, ""); }) + .filter(Boolean) + .filter(function (host) { return !/^unknown$/i.test(host); }); + if (settingsHost && hosts.indexOf(settingsHost) >= 0) return settingsHost; + if (settingsHost) return settingsHost; + hosts.sort(); + return hosts[0] || ""; + } + + function rewriteUnknownCategoryBuilderQueryBody(body) { + if (typeof body !== "string") return body; + if (body.indexOf("aw-watcher-window_unknown") === -1 && body.indexOf("aw-watcher-afk_unknown") === -1) { + return body; + } + const preferredHost = getPreferredWindowHostFromBuckets(); + if (!preferredHost) return body; + return body + .replace(/aw-watcher-window_unknown/g, "aw-watcher-window_" + preferredHost) + .replace(/aw-watcher-afk_unknown/g, "aw-watcher-afk_" + preferredHost); + } + + function installCategoryBuilderNetworkPatch() { + if (networkPatchesInstalled) return; + networkPatchesInstalled = true; + + const originalFetch = window.fetch ? window.fetch.bind(window) : null; + if (originalFetch) { + window.fetch = function (input, init) { + try { + const url = typeof input === "string" ? input : String(input && input.url || ""); + if (/\/api\/0\/query\/?$/i.test(url) && init && typeof init.body === "string") { + init = Object.assign({}, init, { + body: rewriteUnknownCategoryBuilderQueryBody(init.body) + }); + } + } catch (error) { + } + return originalFetch(input, init); + }; + } + + if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) { + const proto = window.XMLHttpRequest.prototype; + if (!proto.__awRuCategoryBuilderPatched) { + const originalOpen = proto.open; + const originalSend = proto.send; + proto.open = function (method, url) { + this.__awRuMethod = method; + this.__awRuUrl = url; + return originalOpen.apply(this, arguments); + }; + proto.send = function (body) { + try { + const url = String(this.__awRuUrl || ""); + if (/\/api\/0\/query\/?$/i.test(url) && typeof body === "string") { + body = rewriteUnknownCategoryBuilderQueryBody(body); + } + } catch (error) { + } + return originalSend.call(this, body); + }; + proto.__awRuCategoryBuilderPatched = true; + } + } + } + + function patchCategoryBuilderHostLabel(root) { + if (!/^#\/settings\/category-builder(?:[/?#]|$)/i.test(window.location.hash || "")) return; + const preferredHost = getPreferredWindowHostFromBuckets(); + if (!preferredHost) return; + Array.from(root.querySelectorAll("*")).forEach(function (element) { + if (element.children.length) return; + const text = element.textContent || ""; + if (!/Имя хоста:\s*(unknown|неизвестно)\b|Hostname:\s*unknown\b/i.test(text)) return; + const next = text + .replace(/Имя хоста:\s*(unknown|неизвестно)\b/i, "Имя хоста: " + preferredHost) + .replace(/Hostname:\s*unknown\b/i, "Hostname: " + preferredHost); + if (next !== text) { + element.textContent = next; + } + }); + } + function applyPatch() { enforceSafeActivityViewForPveHost(); ensureSettingsHost(); + ensureHostGroupsData().catch(function () {}); + installCategoryBuilderNetworkPatch(); injectStyles(); walk(document.body); translateAttributes(document.body); hideNoiseNavigation(document.body); + patchCategoryBuilderHostLabel(document.body); injectPveAuditCenter(document.body); injectDlpNavigation(document.body); injectDlpReviewCenter(document.body); diff --git a/install-kit-awindows-20260427-211240.tar.gz b/install-kit-awindows-20260427-211240.tar.gz index 7c7680f..7020eaf 100644 Binary files a/install-kit-awindows-20260427-211240.tar.gz and b/install-kit-awindows-20260427-211240.tar.gz differ diff --git a/install-kit-awindows-20260427-211240.zip b/install-kit-awindows-20260427-211240.zip index 0b33d23..02d4637 100644 Binary files a/install-kit-awindows-20260427-211240.zip and b/install-kit-awindows-20260427-211240.zip differ diff --git a/install-kit-awindows-20260427-211240/MANIFEST.txt b/install-kit-awindows-20260427-211240/MANIFEST.txt index 7513f6f..5cf8d81 100644 --- a/install-kit-awindows-20260427-211240/MANIFEST.txt +++ b/install-kit-awindows-20260427-211240/MANIFEST.txt @@ -13,9 +13,9 @@ bbef175cb77dd53aa07452dbb2fe8797f38b58f42372005c3404c8dc9d6f8e13 install-kit-aw b8f8b6bc504a51cd87db3f46c35a27295b395ea516533068f96af35f8b720434 install-kit-awindows-20260427-211240/ansible/provision_proxmox_ct_matrix_and_deploy_aw.yml d35bc97b6de18f0006cbbad4adf8a8a5db8ed912997d8fc47c7f11fa9247e907 install-kit-awindows-20260427-211240/ansible/tasks/provision_ct_and_deploy_aw.yml a50dbadbf619342c2178e255b68f69a36503756daf80eedd9170311c63964f2e install-kit-awindows-20260427-211240/aw-server/activitywatch-server.service -1ef77d865937a8fac15e47fd95b046fc713306f7e0b5a386a9dadd1d4c6ad0be install-kit-awindows-20260427-211240/aw-server/apply_webui_ru_patch.sh +2dbf55d4a8f204ebdc97af926d90435932c0aad7a2431e2b9987e47c5abf71a9 install-kit-awindows-20260427-211240/aw-server/apply_webui_ru_patch.sh 07d4e583f6e9757a11f01558e1f15cfd73c4d82695f1768204f2f50621712168 install-kit-awindows-20260427-211240/aw-server/aw-host-groups.json -76d9d3f3b1984fb2d668bc3bab6bb2a6300c0e5e2cae1b123da7237ca13484e3 install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js +c149bb3a92ad712bad184eb034f6a683b18117e84300116633a3575f07697395 install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js 7c5952f8f0a8590e849ea8381bfcd7059b138250bca8551bd5625f395eb66cd8 install-kit-awindows-20260427-211240/aw-server/aw-server.env.example 98c0bed353bbda0fa7a69df23f3b008cb0e8e70cdff6cc63330d4caf79fd3280 install-kit-awindows-20260427-211240/aw-server/aw-sw-cleanup.js dce731fdfdcfd773c154d12dbd6b9e621a0bff17ced5a05a65f0fdcb1adcb70f install-kit-awindows-20260427-211240/aw-server/install_aw_server.sh diff --git a/install-kit-awindows-20260427-211240/aw-server/apply_webui_ru_patch.sh b/install-kit-awindows-20260427-211240/aw-server/apply_webui_ru_patch.sh index 2d37b7b..1b7c240 100755 --- a/install-kit-awindows-20260427-211240/aw-server/apply_webui_ru_patch.sh +++ b/install-kit-awindows-20260427-211240/aw-server/apply_webui_ru_patch.sh @@ -23,6 +23,8 @@ TRENDS_NEEDLE='this.activityStore.query_category_time_by_period(r)' TRENDS_REPLACEMENT='this.activityStore.ensure_loaded(r)' TIMESPIRAL_NEEDLE='start:new Date("2022-08-08")' TIMESPIRAL_REPLACEMENT='start:new Date(Date.now()-12*36e5)' +CATEGORY_HELPER_NEEDLE='hostname:t.hostnameChoices[0]' +CATEGORY_HELPER_REPLACEMENT='hostname:t.hostnameChoices.filter((function(t){return"unknown"!==t}))[0]||t.hostnameChoices[0]' [[ -f "$PATCH_JS_SRC" ]] || { echo "missing $PATCH_JS_SRC" >&2; exit 1; } [[ -f "$SW_CLEANUP_SRC" ]] || { echo "missing $SW_CLEANUP_SRC" >&2; exit 1; } @@ -85,4 +87,25 @@ else echo "Timespiral hotfix skipped: chunk not found" fi +category_helper_chunk="$(grep -Rsl "$CATEGORY_HELPER_NEEDLE" "$WEBUI_DIR/js"/*.js 2>/dev/null | head -n 1 || true)" +if [[ -n "$category_helper_chunk" ]]; then + cp "$category_helper_chunk" "$category_helper_chunk.bak.$TS" + python3 - "$category_helper_chunk" "$CATEGORY_HELPER_NEEDLE" "$CATEGORY_HELPER_REPLACEMENT" <<'PY' +from pathlib import Path +import sys + +path = Path(sys.argv[1]) +old = sys.argv[2] +new = sys.argv[3] +content = path.read_text() +if old in content: + path.write_text(content.replace(old, new, 1)) + print(f"Category helper host hotfix applied to {path}") +else: + print(f"Category helper host hotfix already present in {path}") +PY +else + echo "Category helper host hotfix skipped: chunk not found" +fi + echo "RU patch applied to $WEBUI_DIR (ru-patch-v5.js?v=$patch_hash)" diff --git a/install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js b/install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js index 1052651..363ae10 100755 --- a/install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js +++ b/install-kit-awindows-20260427-211240/aw-server/aw-ru-patch.js @@ -1,6 +1,6 @@ (function () { - window.__awRuPatchVersion = "template-v10-pve-detmir-audit-stable"; - document.documentElement.setAttribute("data-aw-ru-patch", "template-v10-pve-detmir-audit-stable"); + window.__awRuPatchVersion = "template-v11-category-builder-host-fix"; + document.documentElement.setAttribute("data-aw-ru-patch", "template-v11-category-builder-host-fix"); const exact = new Map([ ["ActivityWatch", "АктивВотч"], @@ -1419,6 +1419,7 @@ let trendsRedirectInFlight = false; let settingsHostFetchInFlight = false; let applyPatchScheduled = false; + let networkPatchesInstalled = false; function getTrendsHostFromSettings(settings) { if (!settings || typeof settings !== "object") return ""; @@ -1479,13 +1480,108 @@ }); } + function getPreferredWindowHostFromBuckets() { + const state = getHostGroupsState(); + const rawBuckets = state && state.buckets ? state.buckets : {}; + const settingsHost = normalizeText(window.__awRuPatchSettingsHost || ""); + const bucketIds = Array.isArray(rawBuckets) + ? rawBuckets.map(function (item) { return item && item.id ? String(item.id) : ""; }) + : Object.keys(rawBuckets || {}); + const hosts = bucketIds + .filter(function (bucketId) { return /^aw-watcher-window_/i.test(bucketId); }) + .map(function (bucketId) { return bucketId.replace(/^aw-watcher-window_/i, ""); }) + .filter(Boolean) + .filter(function (host) { return !/^unknown$/i.test(host); }); + if (settingsHost && hosts.indexOf(settingsHost) >= 0) return settingsHost; + if (settingsHost) return settingsHost; + hosts.sort(); + return hosts[0] || ""; + } + + function rewriteUnknownCategoryBuilderQueryBody(body) { + if (typeof body !== "string") return body; + if (body.indexOf("aw-watcher-window_unknown") === -1 && body.indexOf("aw-watcher-afk_unknown") === -1) { + return body; + } + const preferredHost = getPreferredWindowHostFromBuckets(); + if (!preferredHost) return body; + return body + .replace(/aw-watcher-window_unknown/g, "aw-watcher-window_" + preferredHost) + .replace(/aw-watcher-afk_unknown/g, "aw-watcher-afk_" + preferredHost); + } + + function installCategoryBuilderNetworkPatch() { + if (networkPatchesInstalled) return; + networkPatchesInstalled = true; + + const originalFetch = window.fetch ? window.fetch.bind(window) : null; + if (originalFetch) { + window.fetch = function (input, init) { + try { + const url = typeof input === "string" ? input : String(input && input.url || ""); + if (/\/api\/0\/query\/?$/i.test(url) && init && typeof init.body === "string") { + init = Object.assign({}, init, { + body: rewriteUnknownCategoryBuilderQueryBody(init.body) + }); + } + } catch (error) { + } + return originalFetch(input, init); + }; + } + + if (window.XMLHttpRequest && window.XMLHttpRequest.prototype) { + const proto = window.XMLHttpRequest.prototype; + if (!proto.__awRuCategoryBuilderPatched) { + const originalOpen = proto.open; + const originalSend = proto.send; + proto.open = function (method, url) { + this.__awRuMethod = method; + this.__awRuUrl = url; + return originalOpen.apply(this, arguments); + }; + proto.send = function (body) { + try { + const url = String(this.__awRuUrl || ""); + if (/\/api\/0\/query\/?$/i.test(url) && typeof body === "string") { + body = rewriteUnknownCategoryBuilderQueryBody(body); + } + } catch (error) { + } + return originalSend.call(this, body); + }; + proto.__awRuCategoryBuilderPatched = true; + } + } + } + + function patchCategoryBuilderHostLabel(root) { + if (!/^#\/settings\/category-builder(?:[/?#]|$)/i.test(window.location.hash || "")) return; + const preferredHost = getPreferredWindowHostFromBuckets(); + if (!preferredHost) return; + Array.from(root.querySelectorAll("*")).forEach(function (element) { + if (element.children.length) return; + const text = element.textContent || ""; + if (!/Имя хоста:\s*(unknown|неизвестно)\b|Hostname:\s*unknown\b/i.test(text)) return; + const next = text + .replace(/Имя хоста:\s*(unknown|неизвестно)\b/i, "Имя хоста: " + preferredHost) + .replace(/Hostname:\s*unknown\b/i, "Hostname: " + preferredHost); + if (next !== text) { + element.textContent = next; + } + }); + } + function applyPatch() { enforceSafeActivityViewForPveHost(); ensureSettingsHost(); + ensureHostGroupsData().catch(function () {}); + installCategoryBuilderNetworkPatch(); injectStyles(); walk(document.body); translateAttributes(document.body); hideNoiseNavigation(document.body); + patchCategoryBuilderHostLabel(document.body); injectPveAuditCenter(document.body); injectDlpNavigation(document.body); injectDlpReviewCenter(document.body);