Bump to v1.1.0, enable network and docker detectors
- Version bump reflecting new features (sounds, tap reaction, docker detector) - Rename title to Kao - Enable network and docker detectors by default Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -45,7 +45,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "network",
|
"name": "network",
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"script": "detectors/network.py",
|
"script": "detectors/network.py",
|
||||||
"env": {
|
"env": {
|
||||||
"CHECK_INTERVAL": "60",
|
"CHECK_INTERVAL": "60",
|
||||||
@@ -55,7 +55,7 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "docker",
|
"name": "docker",
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"script": "detectors/docker.py",
|
"script": "detectors/docker.py",
|
||||||
"env": {
|
"env": {
|
||||||
"CHECK_INTERVAL": "60",
|
"CHECK_INTERVAL": "60",
|
||||||
|
|||||||
119
index.html
119
index.html
@@ -1,9 +1,12 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
<meta
|
||||||
<title>Sentry-Emote</title>
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1.0, user-scalable=no"
|
||||||
|
/>
|
||||||
|
<title>Kao</title>
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -42,7 +45,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes breathe {
|
@keyframes breathe {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
@@ -58,9 +62,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes shake {
|
@keyframes shake {
|
||||||
0%, 100% { transform: translateX(0); }
|
0%,
|
||||||
25% { transform: translateX(-5px); }
|
100% {
|
||||||
75% { transform: translateX(5px); }
|
transform: translateX(0);
|
||||||
|
}
|
||||||
|
25% {
|
||||||
|
transform: translateX(-5px);
|
||||||
|
}
|
||||||
|
75% {
|
||||||
|
transform: translateX(5px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Popping animation - scale up for Notifications */
|
/* Popping animation - scale up for Notifications */
|
||||||
@@ -69,7 +80,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes pop {
|
@keyframes pop {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
@@ -83,7 +95,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes celebrate {
|
@keyframes celebrate {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
transform: translateY(0) rotate(0deg);
|
transform: translateY(0) rotate(0deg);
|
||||||
}
|
}
|
||||||
25% {
|
25% {
|
||||||
@@ -100,7 +113,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes float {
|
@keyframes float {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
@@ -114,7 +128,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes bounce {
|
@keyframes bounce {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
transform: translateY(0);
|
transform: translateY(0);
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
@@ -128,7 +143,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes sway {
|
@keyframes sway {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
transform: rotate(0deg);
|
transform: rotate(0deg);
|
||||||
}
|
}
|
||||||
25% {
|
25% {
|
||||||
@@ -145,7 +161,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes blink {
|
@keyframes blink {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
}
|
}
|
||||||
50% {
|
50% {
|
||||||
@@ -159,7 +176,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes search {
|
@keyframes search {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
transform: translateX(0);
|
transform: translateX(0);
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
}
|
||||||
@@ -179,7 +197,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes sleep {
|
@keyframes sleep {
|
||||||
0%, 100% {
|
0%,
|
||||||
|
100% {
|
||||||
opacity: 0.4;
|
opacity: 0.4;
|
||||||
transform: scale(1);
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
@@ -189,20 +208,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="emote" class="breathing">( ^_^)</div>
|
<div id="emote" class="breathing">( ^_^)</div>
|
||||||
<div id="message">Loading...</div>
|
<div id="message">Loading...</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
const emoteEl = document.getElementById('emote');
|
const emoteEl = document.getElementById("emote");
|
||||||
const messageEl = document.getElementById('message');
|
const messageEl = document.getElementById("message");
|
||||||
const POLL_INTERVAL = 2000;
|
const POLL_INTERVAL = 2000;
|
||||||
const VERSION = 'v1.0.0';
|
const VERSION = "v1.1.0";
|
||||||
|
|
||||||
// Sound system
|
// Sound system
|
||||||
let audioCtx = null;
|
let audioCtx = null;
|
||||||
let soundEnabled = new URLSearchParams(window.location.search).get('sound') === 'on';
|
let soundEnabled =
|
||||||
|
new URLSearchParams(window.location.search).get("sound") === "on";
|
||||||
let lastState = null;
|
let lastState = null;
|
||||||
let lastData = null;
|
let lastData = null;
|
||||||
let isReacting = false;
|
let isReacting = false;
|
||||||
@@ -211,19 +231,22 @@
|
|||||||
if (!audioCtx) {
|
if (!audioCtx) {
|
||||||
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
audioCtx = new (window.AudioContext || window.webkitAudioContext)();
|
||||||
}
|
}
|
||||||
if (audioCtx.state === 'suspended') {
|
if (audioCtx.state === "suspended") {
|
||||||
audioCtx.resume();
|
audioCtx.resume();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playTone(frequency, duration, type = 'sine', volume = 0.1) {
|
function playTone(frequency, duration, type = "sine", volume = 0.1) {
|
||||||
if (!soundEnabled || !audioCtx) return;
|
if (!soundEnabled || !audioCtx) return;
|
||||||
const osc = audioCtx.createOscillator();
|
const osc = audioCtx.createOscillator();
|
||||||
const gain = audioCtx.createGain();
|
const gain = audioCtx.createGain();
|
||||||
osc.type = type;
|
osc.type = type;
|
||||||
osc.frequency.value = frequency;
|
osc.frequency.value = frequency;
|
||||||
gain.gain.value = volume;
|
gain.gain.value = volume;
|
||||||
gain.gain.exponentialRampToValueAtTime(0.001, audioCtx.currentTime + duration);
|
gain.gain.exponentialRampToValueAtTime(
|
||||||
|
0.001,
|
||||||
|
audioCtx.currentTime + duration,
|
||||||
|
);
|
||||||
osc.connect(gain);
|
osc.connect(gain);
|
||||||
gain.connect(audioCtx.destination);
|
gain.connect(audioCtx.destination);
|
||||||
osc.start();
|
osc.start();
|
||||||
@@ -244,7 +267,7 @@
|
|||||||
|
|
||||||
function playNotifySound() {
|
function playNotifySound() {
|
||||||
// Gentle ping
|
// Gentle ping
|
||||||
playTone(880, 0.1, 'sine', 0.08);
|
playTone(880, 0.1, "sine", 0.08);
|
||||||
}
|
}
|
||||||
|
|
||||||
function playRecoverySound() {
|
function playRecoverySound() {
|
||||||
@@ -256,7 +279,7 @@
|
|||||||
|
|
||||||
function playReactSound() {
|
function playReactSound() {
|
||||||
// Cute surprised chirp
|
// Cute surprised chirp
|
||||||
playTone(600, 0.08, 'sine', 0.06);
|
playTone(600, 0.08, "sine", 0.06);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleStateChange(newState, newEmote) {
|
function handleStateChange(newState, newEmote) {
|
||||||
@@ -267,13 +290,17 @@
|
|||||||
|
|
||||||
// State transitions that trigger sounds
|
// State transitions that trigger sounds
|
||||||
if (newState !== lastState) {
|
if (newState !== lastState) {
|
||||||
if (newState === 'critical') {
|
if (newState === "critical") {
|
||||||
playCriticalSound();
|
playCriticalSound();
|
||||||
} else if (newState === 'warning') {
|
} else if (newState === "warning") {
|
||||||
playWarningSound();
|
playWarningSound();
|
||||||
} else if (newState === 'notify') {
|
} else if (newState === "notify") {
|
||||||
playNotifySound();
|
playNotifySound();
|
||||||
} else if (newState === 'optimal' && lastState !== 'optimal' && lastState !== 'sleeping') {
|
} else if (
|
||||||
|
newState === "optimal" &&
|
||||||
|
lastState !== "optimal" &&
|
||||||
|
lastState !== "sleeping"
|
||||||
|
) {
|
||||||
// Recovery - also check for celebration emote
|
// Recovery - also check for celebration emote
|
||||||
playRecoverySound();
|
playRecoverySound();
|
||||||
}
|
}
|
||||||
@@ -282,7 +309,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Handle tap - enable sound and show reaction
|
// Handle tap - enable sound and show reaction
|
||||||
document.body.addEventListener('click', () => {
|
document.body.addEventListener("click", () => {
|
||||||
// Enable sound on first tap (browser autoplay policy)
|
// Enable sound on first tap (browser autoplay policy)
|
||||||
if (!soundEnabled) {
|
if (!soundEnabled) {
|
||||||
soundEnabled = true;
|
soundEnabled = true;
|
||||||
@@ -298,8 +325,8 @@
|
|||||||
const prevMsg = messageEl.textContent;
|
const prevMsg = messageEl.textContent;
|
||||||
|
|
||||||
// Surprised face!
|
// Surprised face!
|
||||||
emoteEl.textContent = '( °o°)';
|
emoteEl.textContent = "( °o°)";
|
||||||
emoteEl.className = 'popping';
|
emoteEl.className = "popping";
|
||||||
messageEl.textContent = `Kao ${VERSION}`;
|
messageEl.textContent = `Kao ${VERSION}`;
|
||||||
playReactSound();
|
playReactSound();
|
||||||
|
|
||||||
@@ -320,22 +347,22 @@
|
|||||||
|
|
||||||
// Also init if ?sound=on
|
// Also init if ?sound=on
|
||||||
if (soundEnabled) {
|
if (soundEnabled) {
|
||||||
document.addEventListener('DOMContentLoaded', initAudio);
|
document.addEventListener("DOMContentLoaded", initAudio);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchStatus() {
|
async function fetchStatus() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/status');
|
const response = await fetch("/status");
|
||||||
if (!response.ok) throw new Error('Failed to fetch');
|
if (!response.ok) throw new Error("Failed to fetch");
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
updateDisplay(data);
|
updateDisplay(data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Connection lost state
|
// Connection lost state
|
||||||
emoteEl.textContent = '( ?.?)';
|
emoteEl.textContent = "( ?.?)";
|
||||||
emoteEl.style.color = '#888888';
|
emoteEl.style.color = "#888888";
|
||||||
emoteEl.className = 'searching';
|
emoteEl.className = "searching";
|
||||||
messageEl.style.color = '#888888';
|
messageEl.style.color = "#888888";
|
||||||
messageEl.textContent = '';
|
messageEl.textContent = "";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,10 +381,10 @@
|
|||||||
|
|
||||||
// Only show message when there's something to report
|
// Only show message when there's something to report
|
||||||
const topEvent = data.active_events && data.active_events[0];
|
const topEvent = data.active_events && data.active_events[0];
|
||||||
messageEl.textContent = (topEvent && topEvent.message) || '';
|
messageEl.textContent = (topEvent && topEvent.message) || "";
|
||||||
|
|
||||||
// Update animation class
|
// Update animation class
|
||||||
emoteEl.className = '';
|
emoteEl.className = "";
|
||||||
if (data.animation) {
|
if (data.animation) {
|
||||||
emoteEl.classList.add(data.animation);
|
emoteEl.classList.add(data.animation);
|
||||||
}
|
}
|
||||||
@@ -367,5 +394,5 @@
|
|||||||
fetchStatus();
|
fetchStatus();
|
||||||
setInterval(fetchStatus, POLL_INTERVAL);
|
setInterval(fetchStatus, POLL_INTERVAL);
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
Reference in New Issue
Block a user