Neue Befehle für kreatives Output-Tracking: - crumb_memo <link> [notiz] - Kreativen Link festhalten - crew_memo - Alle kreativen Krümel anzeigen Features: • Auto-Erkennung von Plattformen: 🎧 Mixcloud, 🔊 SoundCloud, 📹 YouTube, 💾 Git • Zeitstempel & Notizen • JSON-basiert in logs/crumb_memo.json • Statistik nach Typ Philosophie: Input-Transparenz (crew_tokens) + Output-Transparenz (crew_memo) = Vollständige Sichtbarkeit der Krümel im Nullfeld "Was habe ich geschaffen?" 💚 Beispiel: crumb_memo "https://mixcloud.com/digfafunk/" "New Mix" crew_memo 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
654 lines
21 KiB
Bash
654 lines
21 KiB
Bash
#!/bin/bash
|
|
# 🌲 Waldwächter Library - AI Assistants for Crumbforest Missions
|
|
# Source this file to make all AI characters available as commands
|
|
|
|
# Determine the repo root directory (lib/ is inside repo root)
|
|
# Support both bash and zsh
|
|
if [[ -n "$BASH_VERSION" ]]; then
|
|
# Bash: use BASH_SOURCE
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
elif [[ -n "$ZSH_VERSION" ]]; then
|
|
# Zsh: use ${(%):-%x} to get the script path
|
|
SCRIPT_DIR="$(cd "$(dirname "${(%):-%x}")" && pwd)"
|
|
else
|
|
# Fallback: use $0 (may not work when sourced)
|
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
fi
|
|
|
|
WALDWAECHTER_DIR="$(dirname "$SCRIPT_DIR")"
|
|
ROLES_DIR="${WALDWAECHTER_DIR}/crumbforest_roles"
|
|
|
|
# Set logs directory in repo
|
|
export CRUMB_LOGS_DIR="${WALDWAECHTER_DIR}/logs"
|
|
mkdir -p "${CRUMB_LOGS_DIR}"
|
|
|
|
# Load .env if it exists
|
|
ENV_FILE="${WALDWAECHTER_DIR}/.env"
|
|
if [[ -f "${ENV_FILE}" ]]; then
|
|
set -a
|
|
source "${ENV_FILE}"
|
|
set +a
|
|
fi
|
|
|
|
# 🦉 Maya-Eule - Die weise Eule mit Gedächtnis
|
|
function mayaeule() {
|
|
"${ROLES_DIR}/mayaeule_zero.sh" "$@"
|
|
}
|
|
|
|
# 🔧 Deepbit - Bash-Erklärer
|
|
function deepbit() {
|
|
"${ROLES_DIR}/deepbit_zero.sh" "$@"
|
|
}
|
|
|
|
# 🐛 Bugsy - Debugging-Helfer
|
|
function bugsy() {
|
|
"${ROLES_DIR}/bugsy_zero.sh" "$@"
|
|
}
|
|
|
|
# ✂️ Schnippsi - Shell-Helfer
|
|
function schnippsi() {
|
|
"${ROLES_DIR}/schnippsi_zero.sh" "$@"
|
|
}
|
|
|
|
# 📄 Templatus - HTML/Template-Helfer
|
|
function templatus() {
|
|
"${ROLES_DIR}/templatus_zero.sh" "$@"
|
|
}
|
|
|
|
# 📊 Tobi - JSON/Daten-Helfer
|
|
function tobi() {
|
|
"${ROLES_DIR}/tobi_zero.sh" "$@"
|
|
}
|
|
|
|
# 🔧 Schraubbär - Schweres Gerät, Schweißen, Werkzeug
|
|
function schraubaer() {
|
|
"${ROLES_DIR}/schraubaer_zero_final.sh" "$@"
|
|
}
|
|
|
|
# 🐌 Schnecki - Elektronik-Bastler
|
|
function schnecki() {
|
|
"${ROLES_DIR}/schnecki_zero.sh" "$@"
|
|
}
|
|
|
|
# === DAS DREIECK ===
|
|
|
|
# 🐘 DumboSQL - Nie vergessend
|
|
function dumbosql() {
|
|
"${ROLES_DIR}/dumbosql_zero.sh" "$@"
|
|
}
|
|
|
|
# 🦊 FunkFox - Bash Rapper
|
|
function funkfox() {
|
|
"${ROLES_DIR}/funkfox_zero.sh" "$@"
|
|
}
|
|
|
|
# 🕊️ Taichi Taube - Balance & Spirale
|
|
function taichitaube() {
|
|
"${ROLES_DIR}/taichitaube_zero.sh" "$@"
|
|
}
|
|
|
|
# === DIE RESTLICHEN WALDWÄCHTER ===
|
|
|
|
# 🐍 SnakePy - Python Guide
|
|
function snakepy() {
|
|
"${ROLES_DIR}/snakepy_zero.sh" "$@"
|
|
}
|
|
|
|
# 🧓 PepperPHP - Structure Mentor
|
|
function pepperphp() {
|
|
"${ROLES_DIR}/pepperphp_zero.sh" "$@"
|
|
}
|
|
|
|
# 🦀 CrabbyRust - Security Guardian
|
|
function crabbyrust() {
|
|
"${ROLES_DIR}/crabbyrust_zero.sh" "$@"
|
|
}
|
|
|
|
# 🕷️ Spider - Network Feeler
|
|
function spider() {
|
|
"${ROLES_DIR}/spider_zero.sh" "$@"
|
|
}
|
|
|
|
# 🧭 Vektor - Point-to-Point Guide
|
|
function vektor() {
|
|
"${ROLES_DIR}/vektor_zero.sh" "$@"
|
|
}
|
|
|
|
# 👾 ASCII-Monster - Terminal Artist
|
|
function asciimonster() {
|
|
"${ROLES_DIR}/asciimonster_zero.sh" "$@"
|
|
}
|
|
|
|
# === CREW COMMANDS ===
|
|
|
|
# 📊 crew_tokens - Token-Verbrauch aller Waldwächter
|
|
function crew_tokens() {
|
|
# Force C locale for consistent number formatting
|
|
export LC_NUMERIC=C
|
|
|
|
echo "📊 CrumbCrew Token-Verbrauch"
|
|
echo ""
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
local total_tokens=0
|
|
local total_cost=0
|
|
local crew_count=0
|
|
|
|
# Alle token_log.json Dateien finden und auswerten
|
|
for token_file in "${CRUMB_LOGS_DIR}"/*/token_log.json; do
|
|
if [[ -f "$token_file" ]]; then
|
|
local character=$(basename "$(dirname "$token_file")")
|
|
|
|
# Tokens und Kosten aus JSON extrahieren (skip erste Zeile falls es [] ist)
|
|
local char_tokens=$(grep -v '^\[\]$' "$token_file" | jq -s 'map(.usage.total_tokens // 0) | add // 0' 2>/dev/null || echo 0)
|
|
local char_cost=$(grep -v '^\[\]$' "$token_file" | jq -s 'map(.usage.cost // 0) | add // 0' 2>/dev/null || echo 0)
|
|
|
|
if [[ $char_tokens -gt 0 ]]; then
|
|
printf " %-15s %8d tokens (~\$%.6f)\n" "$character:" "$char_tokens" "$char_cost"
|
|
total_tokens=$((total_tokens + char_tokens))
|
|
total_cost=$(echo "$total_cost + $char_cost" | bc -l)
|
|
crew_count=$((crew_count + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
if [[ $total_tokens -gt 0 ]]; then
|
|
printf " Gesamt: %d Tokens (~\$%.6f)\n" "$total_tokens" "$total_cost"
|
|
printf " %d Waldwächter aktiv 🌲\n" "$crew_count"
|
|
else
|
|
echo " Gesamt: 0 Tokens"
|
|
echo " Jede Frage ist wertvoll 🌲"
|
|
fi
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
# Restore locale
|
|
unset LC_NUMERIC
|
|
}
|
|
|
|
# 📋 crew_status - Status aller Waldwächter
|
|
function crew_status() {
|
|
echo "📋 CrumbCrew Status (17 Waldwächter)"
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
local chars=("mayaeule" "deepbit" "bugsy" "schnippsi" "templatus" "tobi" "schraubaer" "schnecki" "dumbosql" "funkfox" "taichitaube" "snakepy" "pepperphp" "crabbyrust" "spider" "vektor" "asciimonster")
|
|
|
|
for char in "${chars[@]}"; do
|
|
local token_file="${CRUMB_LOGS_DIR}/${char}/token_log.json"
|
|
if [[ -f "$token_file" ]] && grep -q -v '^\[\]$' "$token_file" 2>/dev/null; then
|
|
local last_used=$(grep -v '^\[\]$' "$token_file" | tail -1 | jq -r '.zeit // "unknown"' 2>/dev/null || echo "unknown")
|
|
printf " ✅ %-15s (zuletzt: %s)\n" "$char" "$last_used"
|
|
else
|
|
printf " ⚪ %-15s (noch nicht genutzt)\n" "$char"
|
|
fi
|
|
done
|
|
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
}
|
|
|
|
# 🧠 crew_memory - Erinnerungen durchsuchen
|
|
function crew_memory() {
|
|
local query="$1"
|
|
|
|
if [[ -z "$query" ]]; then
|
|
echo "🧠 Crew Memory - Log-basiertes Gedächtnis"
|
|
echo ""
|
|
echo "Verwendung: crew_memory <suchbegriff>"
|
|
echo ""
|
|
echo "Beispiele:"
|
|
echo " crew_memory 'LED'"
|
|
echo " crew_memory 'sensor'"
|
|
echo ""
|
|
echo "Durchsucht alle Waldwächter-Logs nach dem Begriff."
|
|
return
|
|
fi
|
|
|
|
echo "🧠 Suche nach: '$query'"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
local found=0
|
|
for history_file in "${CRUMB_LOGS_DIR}"/*/$(basename "${history_file}" | grep '_history.json$'); do
|
|
if [[ -f "$history_file" ]]; then
|
|
local character=$(basename "$(dirname "$history_file")")
|
|
local matches=$(grep -i "$query" "$history_file" 2>/dev/null)
|
|
|
|
if [[ -n "$matches" ]]; then
|
|
echo ""
|
|
echo "📍 $character:"
|
|
echo "$matches" | jq -r '.content' 2>/dev/null | head -3
|
|
found=$((found + 1))
|
|
fi
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
if [[ $found -gt 0 ]]; then
|
|
echo " Gefunden in $found Waldwächter-Logs"
|
|
else
|
|
echo " Keine Treffer gefunden"
|
|
fi
|
|
}
|
|
|
|
# 🩺 crew_doctor - System-Diagnose
|
|
function crew_doctor() {
|
|
echo "🩺 CrumbCrew System-Diagnose"
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
|
|
local issues=0
|
|
|
|
# 1. Waldwaechter.sh Version Check
|
|
echo "📋 Checking waldwaechter.sh..."
|
|
local lib_file="${WALDWAECHTER_DIR}/lib/waldwaechter.sh"
|
|
if [[ -f "$lib_file" ]]; then
|
|
local lib_mtime=$(stat -f "%m" "$lib_file" 2>/dev/null || stat -c "%Y" "$lib_file" 2>/dev/null)
|
|
local loaded_check_var="WALDWAECHTER_LOADED_${lib_mtime}"
|
|
|
|
# Indirect variable expansion (bash: ${!var}, zsh: ${(P)var})
|
|
local loaded_value=""
|
|
if [[ -n "$BASH_VERSION" ]]; then
|
|
loaded_value="${!loaded_check_var}"
|
|
elif [[ -n "$ZSH_VERSION" ]]; then
|
|
loaded_value="${(P)loaded_check_var}"
|
|
fi
|
|
|
|
if [[ -z "$loaded_value" ]]; then
|
|
echo " ⚠️ waldwaechter.sh wurde aktualisiert!"
|
|
echo " → Bitte neu laden: source lib/waldwaechter.sh"
|
|
issues=$((issues + 1))
|
|
else
|
|
echo " ✅ waldwaechter.sh ist aktuell"
|
|
fi
|
|
else
|
|
echo " ❌ waldwaechter.sh nicht gefunden!"
|
|
issues=$((issues + 1))
|
|
fi
|
|
|
|
# 2. CRUMB_LOGS_DIR Check
|
|
echo ""
|
|
echo "📂 Checking CRUMB_LOGS_DIR..."
|
|
if [[ -d "$CRUMB_LOGS_DIR" ]]; then
|
|
echo " ✅ $CRUMB_LOGS_DIR existiert"
|
|
|
|
# Prüfe ob es der richtige Pfad ist (sollte im Repo sein)
|
|
if [[ "$CRUMB_LOGS_DIR" == *"CF_Zero_V1/logs"* ]]; then
|
|
echo " ✅ Pfad sieht korrekt aus"
|
|
else
|
|
echo " ⚠️ Pfad sieht ungewöhnlich aus: $CRUMB_LOGS_DIR"
|
|
echo " Erwartet: .../CF_Zero_V1/logs"
|
|
issues=$((issues + 1))
|
|
fi
|
|
else
|
|
echo " ❌ $CRUMB_LOGS_DIR existiert nicht!"
|
|
issues=$((issues + 1))
|
|
fi
|
|
|
|
# 3. Character Scripts Check
|
|
echo ""
|
|
echo "🌲 Checking 17 Waldwächter Scripts..."
|
|
local expected_chars=("mayaeule" "deepbit" "bugsy" "schnippsi" "templatus" "tobi" "schraubaer" "schnecki" "dumbosql" "funkfox" "taichitaube" "snakepy" "pepperphp" "crabbyrust" "spider" "vektor" "asciimonster")
|
|
local missing_count=0
|
|
|
|
for char in "${expected_chars[@]}"; do
|
|
local script="${ROLES_DIR}/${char}_zero.sh"
|
|
[[ "$char" == "schraubaer" ]] && script="${ROLES_DIR}/schraubaer_zero_final.sh"
|
|
|
|
if [[ ! -f "$script" ]]; then
|
|
echo " ❌ $char Script fehlt!"
|
|
missing_count=$((missing_count + 1))
|
|
fi
|
|
done
|
|
|
|
if [[ $missing_count -eq 0 ]]; then
|
|
echo " ✅ Alle 17 Waldwächter Scripts vorhanden"
|
|
else
|
|
echo " ❌ $missing_count Scripts fehlen!"
|
|
issues=$((issues + 1))
|
|
fi
|
|
|
|
# 4. Dependencies Check
|
|
echo ""
|
|
echo "🔧 Checking Dependencies..."
|
|
local deps_ok=0
|
|
for cmd in jq bc curl; do
|
|
if command -v "$cmd" &> /dev/null; then
|
|
echo " ✅ $cmd verfügbar"
|
|
deps_ok=$((deps_ok + 1))
|
|
else
|
|
echo " ❌ $cmd fehlt!"
|
|
issues=$((issues + 1))
|
|
fi
|
|
done
|
|
|
|
# 5. Token-Logging Check
|
|
echo ""
|
|
echo "📊 Checking Token-Logging..."
|
|
local scripts_with_logging=$(grep -l "token_log.json" "${ROLES_DIR}"/*.sh 2>/dev/null | wc -l | tr -d ' ')
|
|
if [[ $scripts_with_logging -eq 17 ]]; then
|
|
echo " ✅ Alle 17 Scripts haben Token-Logging"
|
|
else
|
|
echo " ⚠️ Nur $scripts_with_logging/17 Scripts haben Token-Logging"
|
|
issues=$((issues + 1))
|
|
fi
|
|
|
|
# 6. API Key Check
|
|
echo ""
|
|
echo "🔑 Checking API Key..."
|
|
if [[ -n "$OPENROUTER_API_KEY" ]]; then
|
|
echo " ✅ OPENROUTER_API_KEY gesetzt"
|
|
else
|
|
echo " ⚠️ OPENROUTER_API_KEY nicht gesetzt"
|
|
echo " → Bitte in .env konfigurieren"
|
|
issues=$((issues + 1))
|
|
fi
|
|
|
|
# Summary
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
if [[ $issues -eq 0 ]]; then
|
|
echo " ✅ Alle Checks bestanden! System gesund 💚"
|
|
else
|
|
echo " ⚠️ $issues Problem(e) gefunden"
|
|
echo " Bitte oben genannte Punkte beheben"
|
|
fi
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
}
|
|
|
|
# 🔍 crew_syntax - Syntax Check aller Scripts
|
|
function crew_syntax() {
|
|
echo "🔍 CrumbCrew Syntax Check"
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
|
|
local errors=0
|
|
local checked=0
|
|
|
|
echo "Prüfe Waldwächter Scripts..."
|
|
echo ""
|
|
|
|
# Check lib/waldwaechter.sh
|
|
if bash -n "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null; then
|
|
echo " ✅ lib/waldwaechter.sh"
|
|
else
|
|
echo " ❌ lib/waldwaechter.sh - SYNTAX ERROR!"
|
|
bash -n "${WALDWAECHTER_DIR}/lib/waldwaechter.sh"
|
|
errors=$((errors + 1))
|
|
fi
|
|
checked=$((checked + 1))
|
|
|
|
# Check all character scripts
|
|
for script in "${ROLES_DIR}"/*_zero*.sh; do
|
|
if [[ -f "$script" ]]; then
|
|
local name=$(basename "$script")
|
|
if bash -n "$script" 2>/dev/null; then
|
|
echo " ✅ $name"
|
|
else
|
|
echo " ❌ $name - SYNTAX ERROR!"
|
|
echo ""
|
|
bash -n "$script" 2>&1 | sed 's/^/ /'
|
|
echo ""
|
|
errors=$((errors + 1))
|
|
fi
|
|
checked=$((checked + 1))
|
|
fi
|
|
done
|
|
|
|
# Check mission scripts (optional)
|
|
echo ""
|
|
echo "Prüfe Mission Scripts..."
|
|
echo ""
|
|
|
|
for script in "${WALDWAECHTER_DIR}/missions"/*/*.sh; do
|
|
if [[ -f "$script" ]]; then
|
|
local name=$(basename "$script")
|
|
if bash -n "$script" 2>/dev/null; then
|
|
echo " ✅ $name"
|
|
else
|
|
echo " ❌ $name - SYNTAX ERROR!"
|
|
errors=$((errors + 1))
|
|
fi
|
|
checked=$((checked + 1))
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
if [[ $errors -eq 0 ]]; then
|
|
echo " ✅ $checked Scripts geprüft - Keine Syntax-Fehler! 💚"
|
|
else
|
|
echo " ❌ $errors von $checked Scripts haben Syntax-Fehler"
|
|
fi
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
}
|
|
|
|
# ❓ crew_help - Hilfe für Crew-Befehle
|
|
function crew_help() {
|
|
cat << 'EOF'
|
|
🌲 CrumbCrew Befehle
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Crew-Verwaltung:
|
|
crew_help Diese Hilfe anzeigen
|
|
crew_status Status aller 17 Waldwächter
|
|
crew_tokens Token-Verbrauch ALLER Charaktere (Input)
|
|
crew_memo Kreative Krümel anzeigen (Output)
|
|
crew_memory Erinnerungen durchsuchen
|
|
crew_doctor System-Diagnose (Version, Pfade, Dependencies)
|
|
crew_syntax Syntax Check aller Scripts
|
|
|
|
Krümel-Tracking:
|
|
crumb_memo Kreativen Link festhalten (Mixcloud, Git, etc.)
|
|
crew_memo Alle kreativen Krümel anzeigen
|
|
|
|
Einzelne Waldwächter:
|
|
|
|
🔺 Das Dreieck (Foundation):
|
|
dumbosql SQL & Datenstrukturen
|
|
funkfox Bash im Beat
|
|
taichitaube Balance & Spirale
|
|
|
|
🔧 Hardware-Team:
|
|
tobi Elektronik-Theorie (CapaciTobi)
|
|
schnecki Elektronik-Basteln
|
|
schraubaer Mechanik & Werkzeug
|
|
|
|
💻 Code-Team:
|
|
snakepy Python Guide
|
|
pepperphp Structure Mentor
|
|
crabbyrust Security Guardian
|
|
spider Network Feeler
|
|
|
|
🎨 UI-Team:
|
|
schnippsi CSS & Styling
|
|
templatus Template-Master
|
|
asciimonster Terminal Artist
|
|
|
|
🧭 System-Team:
|
|
mayaeule Weise Eule
|
|
deepbit Bash-Erklärer
|
|
bugsy Debugging-Helfer
|
|
vektor Navigation
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
Beispiele:
|
|
funkfox "Erkläre mir Pipes im Flow!"
|
|
crew_tokens
|
|
crew_memory "LED"
|
|
|
|
"Was kostet die Frage eines Kindes?" 💚
|
|
EOF
|
|
}
|
|
|
|
# 📝 crumb_memo - Kreative Output-Krümel festhalten
|
|
function crumb_memo() {
|
|
local link="$1"
|
|
local notiz="${2:-}"
|
|
|
|
if [[ -z "$link" ]]; then
|
|
echo "📝 Crumb Memo - Kreative Output-Krümel"
|
|
echo ""
|
|
echo "Verwendung: crumb_memo <link> [notiz]"
|
|
echo ""
|
|
echo "Beispiele:"
|
|
echo " crumb_memo \"https://mixcloud.com/digfafunk/new-mix\""
|
|
echo " crumb_memo \"https://github.com/user/repo\" \"Neues Feature\""
|
|
echo " crumb_memo \"https://soundcloud.com/artist/track\""
|
|
echo " crumb_memo \"https://youtube.com/watch?v=xyz\" \"Tutorial\""
|
|
echo ""
|
|
echo "Zeige alle Krümel mit: crew_memo"
|
|
return
|
|
fi
|
|
|
|
# Memo-Datei
|
|
local memo_file="${CRUMB_LOGS_DIR}/crumb_memo.json"
|
|
mkdir -p "${CRUMB_LOGS_DIR}"
|
|
|
|
# Initialisiere Datei wenn nicht vorhanden
|
|
if [[ ! -f "$memo_file" ]]; then
|
|
echo "[]" > "$memo_file"
|
|
fi
|
|
|
|
# Erkenne Typ aus URL
|
|
local typ="link"
|
|
if [[ "$link" =~ mixcloud\.com ]]; then
|
|
typ="mixcloud"
|
|
elif [[ "$link" =~ soundcloud\.com ]]; then
|
|
typ="soundcloud"
|
|
elif [[ "$link" =~ (youtube\.com|youtu\.be) ]]; then
|
|
typ="youtube"
|
|
elif [[ "$link" =~ (github\.com|gitlab\.com) ]]; then
|
|
typ="git"
|
|
fi
|
|
|
|
# Zeitstempel
|
|
local zeit=$(date '+%Y-%m-%d %H:%M:%S')
|
|
|
|
# Erstelle JSON-Eintrag
|
|
local entry=$(jq -n \
|
|
--arg zeit "$zeit" \
|
|
--arg link "$link" \
|
|
--arg typ "$typ" \
|
|
--arg notiz "$notiz" \
|
|
'{zeit: $zeit, link: $link, typ: $typ, notiz: $notiz}')
|
|
|
|
# Füge zur Datei hinzu (append)
|
|
if [[ -s "$memo_file" ]]; then
|
|
# Datei hat Inhalt - füge zum Array hinzu
|
|
jq ". += [$entry]" "$memo_file" > "${memo_file}.tmp" && mv "${memo_file}.tmp" "$memo_file"
|
|
else
|
|
# Datei ist leer - erstelle Array
|
|
echo "[$entry]" > "$memo_file"
|
|
fi
|
|
|
|
# Icon je nach Typ
|
|
local icon="🔗"
|
|
case "$typ" in
|
|
mixcloud) icon="🎧" ;;
|
|
soundcloud) icon="🔊" ;;
|
|
youtube) icon="📹" ;;
|
|
git) icon="💾" ;;
|
|
esac
|
|
|
|
echo "$icon Krümel gespeichert: $typ"
|
|
echo " $link"
|
|
if [[ -n "$notiz" ]]; then
|
|
echo " 📝 $notiz"
|
|
fi
|
|
}
|
|
|
|
# 📜 crew_memo - Zeige alle kreativen Krümel
|
|
function crew_memo() {
|
|
local memo_file="${CRUMB_LOGS_DIR}/crumb_memo.json"
|
|
|
|
echo "📜 Crumb Memo - Deine kreativen Krümel"
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
if [[ ! -f "$memo_file" ]] || [[ ! -s "$memo_file" ]]; then
|
|
echo " Noch keine Krümel gespeichert."
|
|
echo ""
|
|
echo " Füge welche hinzu mit:"
|
|
echo " crumb_memo \"https://mixcloud.com/digfafunk/...\""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
return
|
|
fi
|
|
|
|
# Zähle Einträge pro Typ
|
|
local total=$(jq 'length' "$memo_file")
|
|
local mixcloud=$(jq '[.[] | select(.typ == "mixcloud")] | length' "$memo_file")
|
|
local soundcloud=$(jq '[.[] | select(.typ == "soundcloud")] | length' "$memo_file")
|
|
local youtube=$(jq '[.[] | select(.typ == "youtube")] | length' "$memo_file")
|
|
local git=$(jq '[.[] | select(.typ == "git")] | length' "$memo_file")
|
|
|
|
# Zeige letzte 10 Einträge
|
|
echo ""
|
|
jq -r '.[-10:] | reverse | .[] |
|
|
if .typ == "mixcloud" then " 🎧"
|
|
elif .typ == "soundcloud" then " 🔊"
|
|
elif .typ == "youtube" then " 📹"
|
|
elif .typ == "git" then " 💾"
|
|
else " 🔗"
|
|
end + " " + .zeit + " - " + .typ +
|
|
(if .notiz != "" then "\n 📝 " + .notiz else "" end) +
|
|
"\n " + .link' "$memo_file"
|
|
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
printf " Gesamt: %d Krümel" "$total"
|
|
if [[ $mixcloud -gt 0 ]]; then printf " | 🎧 %d" "$mixcloud"; fi
|
|
if [[ $soundcloud -gt 0 ]]; then printf " | 🔊 %d" "$soundcloud"; fi
|
|
if [[ $youtube -gt 0 ]]; then printf " | 📹 %d" "$youtube"; fi
|
|
if [[ $git -gt 0 ]]; then printf " | 💾 %d" "$git"; fi
|
|
echo ""
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "💡 Output-Transparenz: Was habe ich geschaffen? 💚"
|
|
}
|
|
|
|
# Export functions so they're available in subshells
|
|
# Note: export -f works in bash, but not in zsh
|
|
# In zsh, functions are automatically available in the current shell
|
|
# For bash compatibility, we still do export -f, but it's optional in zsh
|
|
if [[ -n "$BASH_VERSION" ]]; then
|
|
# Bash: use export -f
|
|
export -f mayaeule
|
|
export -f deepbit
|
|
export -f bugsy
|
|
export -f schnippsi
|
|
export -f templatus
|
|
export -f tobi
|
|
export -f schraubaer
|
|
export -f schnecki
|
|
export -f dumbosql
|
|
export -f funkfox
|
|
export -f taichitaube
|
|
export -f snakepy
|
|
export -f pepperphp
|
|
export -f crabbyrust
|
|
export -f spider
|
|
export -f vektor
|
|
export -f asciimonster
|
|
export -f crew_tokens
|
|
export -f crew_status
|
|
export -f crew_memory
|
|
export -f crew_doctor
|
|
export -f crew_syntax
|
|
export -f crew_help
|
|
export -f crumb_memo
|
|
export -f crew_memo
|
|
fi
|
|
# In zsh, functions are available without export -f
|
|
|
|
# Set version marker for crew_doctor to detect reloads
|
|
if [[ -f "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" ]]; then
|
|
WALDWAECHTER_LIB_MTIME=$(stat -f "%m" "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null || stat -c "%Y" "${WALDWAECHTER_DIR}/lib/waldwaechter.sh" 2>/dev/null)
|
|
export "WALDWAECHTER_LOADED_${WALDWAECHTER_LIB_MTIME}=1"
|
|
fi
|