initial commit

This commit is contained in:
ray
2026-07-12 10:17:17 -04:00
commit dab5a4ebc6
1424 changed files with 330463 additions and 0 deletions
+2
View File
@@ -0,0 +1,2 @@
#!/bin/bash
echo "$(date): $(curl -s "https://www.duckdns.org/update?domains=grajmedia&token=bcef60c5-b45d-4604-ae4d-7aa91fa18ef7&ip=51.81.84.34&verbose=true")" >> ~/duckdns/update.log
+74
View File
@@ -0,0 +1,74 @@
#!/bin/bash
# Auto-save any repos with uncommitted changes to Gitea
# Runs daily via cron — stdout is delivered to Telegram
set -euo pipefail
DATE=$(date '+%Y-%m-%d')
LOGFILE="$HOME/.hermes/logs/git-autosave.log"
mkdir -p "$HOME/.hermes/logs"
# Format: path:branch:prefix
# prefix is 'sudo' for root-owned dirs, empty for normal
REPOS=(
"/mnt/seagate8tb/Websites/ShopProQuote.backup-20260626-2058/spq-v2:main"
"/mnt/seagate8tb/docker:main"
"/etc/nginx:main:sudo"
"/home/ray/.hermes:main"
"/home/ray/homelab-scripts:main"
)
SAVED=()
CLEAN=()
ERRORS=()
for entry in "${REPOS[@]}"; do
IFS=':' read -r DIR BRANCH PREFIX <<< "$entry"
NAME=$(basename "$DIR")
GIT="${PREFIX:+sudo }git"
if [ ! -d "$DIR/.git" ]; then
echo "[$DATE] SKIP $DIR — no .git" >> "$LOGFILE"
continue
fi
cd "$DIR"
if [ -z "$($GIT status --porcelain 2>/dev/null)" ]; then
echo "[$DATE] CLEAN $NAME" >> "$LOGFILE"
CLEAN+=("$NAME")
continue
fi
$GIT pull --rebase origin "$BRANCH" 2>/dev/null || true
$GIT add -A
if $GIT commit -m "auto-save $DATE"; then
if $GIT push origin "$BRANCH" 2>/dev/null; then
echo "[$DATE] SAVED $NAME" >> "$LOGFILE"
SAVED+=("$NAME")
else
echo "[$DATE] PUSH FAILED $NAME" >> "$LOGFILE"
ERRORS+=("$NAME (push failed)")
fi
else
echo "[$DATE] COMMIT FAILED $NAME" >> "$LOGFILE"
ERRORS+=("$NAME (commit failed)")
fi
done
# Build stdout message for delivery
MSG=""
if [ ${#SAVED[@]} -gt 0 ]; then
MSG="${MSG}✓ Saved: ${SAVED[*]}\n"
fi
if [ ${#CLEAN[@]} -gt 0 ]; then
MSG="${MSG}— Clean: ${CLEAN[*]}\n"
fi
if [ ${#ERRORS[@]} -gt 0 ]; then
MSG="${MSG}✗ Errors: ${ERRORS[*]}\n"
fi
if [ -n "$MSG" ]; then
echo -e "Gitea auto-save $DATE\n${MSG}"
fi
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""Daily Scrutiny health check — reports drive status to Telegram."""
import json
import urllib.request
import sys
SCRUTINY_URL = "http://localhost:7272/api/summary"
def get_scrutiny_data():
try:
with urllib.request.urlopen(SCRUTINY_URL, timeout=10) as r:
return json.loads(r.read())
except Exception as e:
print(f"❌ *Scrutiny Health Check Failed*\nCould not reach Scrutiny API: {e}")
sys.exit(0)
def check_drives(data):
devices = data.get("data", {}).get("summary", {})
if not devices:
print("❌ *Scrutiny Health Check*\nNo drives found in Scrutiny.")
return
issues = []
healthy = []
for wwn, info in devices.items():
d = info.get("device", {})
s = info.get("smart", {})
name = d.get("device_name", "?")
model = d.get("model_name", "Unknown")
temp = s.get("temp")
hours = s.get("power_on_hours", 0)
status = d.get("device_status", 0)
# status codes: 0=unknown, 1=pass, 2=fail
if status == 2:
issues.append(f"🔴 *{name}* ({model}) — FAILED status")
continue
elif status == 1:
healthy.append(f"✅ *{name}* ({model}) — Passed")
continue
# Temp warnings (HDDs >50C, SSDs >60C is concerning)
if temp is not None:
if "SSD" in model.upper():
temp_str = f"🌡️ {temp}°C"
if temp > 65:
issues.append(f"🔴 *{name}* ({model}) — Critical temp: {temp}°C")
continue
elif temp > 55:
issues.append(f"⚠️ *{name}* ({model}) — High temp: {temp}°C")
continue
else:
temp_str = f"🌡️ {temp}°C"
if temp > 55:
issues.append(f"🔴 *{name}* ({model}) — Critical temp: {temp}°C")
continue
elif temp > 48:
issues.append(f"⚠️ *{name}* ({model}) — High temp: {temp}°C")
continue
healthy.append(f"✅ *{name}* ({model}) — {temp_str if temp else 'N/A temp'}")
# Build message
lines = ["📀 *Daily Drive Health Check*\n"]
if issues:
lines.append("*⚠️ Issues Found:*")
lines.extend(issues)
lines.append("")
lines.append("*All Drives:*")
lines.extend(healthy)
lines.append("")
lines.append(f"📅 {__import__('datetime').datetime.now().strftime('%b %d, %Y %I:%M %p')}")
lines.append("🛡️ Scrutiny + Hermes")
print("\n".join(lines))
if __name__ == "__main__":
data = get_scrutiny_data()
check_drives(data)