From 72f7ac412967d736bd8074c31f059bac7d0e746c Mon Sep 17 00:00:00 2001 From: jessikitty Date: Tue, 23 Dec 2025 01:29:43 +1100 Subject: [PATCH] Add bash-only version of cleanup script - Works directly in SSH add-on (no Python required) - Line-by-line YAML parsing - Preserves indentation and structure - Color-coded output - Automatic backups with restore script - Removes 19 input_booleans and 10 scripts --- ha_chore_cleanup.sh | 373 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 373 insertions(+) create mode 100644 ha_chore_cleanup.sh diff --git a/ha_chore_cleanup.sh b/ha_chore_cleanup.sh new file mode 100644 index 0000000..28a3b51 --- /dev/null +++ b/ha_chore_cleanup.sh @@ -0,0 +1,373 @@ +#!/bin/bash +################################################################################ +# Home Assistant Chore Cleanup Script (Bash Version) +# Removes unused chore-related entities from YAML configuration files +# Creates backups before making any changes +################################################################################ + +set -e # Exit on error + +# Color codes for output +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# Configuration +CONFIG_DIR="/config" +BACKUP_TIMESTAMP=$(date +%Y%m%d_%H%M%S) +BACKUP_DIR="$CONFIG_DIR/backups/cleanup_$BACKUP_TIMESTAMP" + +# Counters +REMOVED_BOOLEANS=0 +REMOVED_SCRIPTS=0 + +# Arrays to store removed items +declare -a REMOVED_BOOLEAN_NAMES=() +declare -a REMOVED_SCRIPT_NAMES=() + +# Entities to remove +INPUT_BOOLEANS_TO_REMOVE=( + "task_lou_clean_desk_pending" + "task_jess_clean_desk_pending" + "task_william_clean_desk_pending" + "task_xander_clean_desk_pending" + "task_bella_clean_desk_pending" + "task_lou_clean_room_pending" + "task_jess_clean_room_pending" + "task_william_clean_room_pending" + "task_xander_clean_room_pending" + "task_bella_clean_room_pending" + "task_tidy_lounge_pending" + "task_vacuum_room_pending" + "task_get_school_ready_pending" + "task_clean_desks_done_this_week" + "task_clean_rooms_done_this_week" + "task_tidy_lounge_done_this_week" + "task_tidy_kitchen_done_today" + "task_clean_dining_table_done_today" + "task_vacuum_room_done_today" +) + +SCRIPTS_TO_REMOVE=( + "complete_task_dishwasher_unload" + "complete_task_washing_machine_unload" + "complete_task_dryer_unload" + "complete_task_bins_out" + "complete_task_bins_in" + "complete_task_kitty_litter_clean" + "complete_task_kitty_litter_change" + "complete_tidy_lounge" + "complete_vacuum_room" + "complete_get_school_ready" +) + +################################################################################ +# Helper Functions +################################################################################ + +print_header() { + echo "" + echo "======================================================================" + echo "$1" + echo "======================================================================" + echo "" +} + +print_success() { + echo -e "${GREEN}✓${NC} $1" +} + +print_info() { + echo -e "${BLUE}ℹ${NC} $1" +} + +print_warning() { + echo -e "${YELLOW}⚠${NC} $1" +} + +print_error() { + echo -e "${RED}✗${NC} $1" +} + +create_backup_dir() { + mkdir -p "$BACKUP_DIR" + print_success "Created backup directory: $BACKUP_DIR" +} + +backup_file() { + local file="$1" + if [ -f "$file" ]; then + cp "$file" "$BACKUP_DIR/$(basename "$file")" + print_info "Backed up: $(basename "$file")" + return 0 + fi + return 1 +} + +################################################################################ +# YAML Cleaning Functions +################################################################################ + +clean_yaml_entity() { + local file="$1" + local entity_name="$2" + local temp_file="${file}.tmp" + local in_entity=0 + local entity_indent="" + local removed=0 + + # Read file line by line + while IFS= read -r line || [[ -n "$line" ]]; do + # Check if this is the start of our target entity + if echo "$line" | grep -q "^[[:space:]]*${entity_name}:"; then + in_entity=1 + # Capture the indentation level + entity_indent=$(echo "$line" | sed 's/[^[:space:]].*//') + removed=1 + continue # Skip this line + fi + + # If we're in the entity block + if [ $in_entity -eq 1 ]; then + # Check if we've reached the next entity at same indent level + if echo "$line" | grep -q "^${entity_indent}[^[:space:]]"; then + in_entity=0 + else + continue # Skip this line (part of entity definition) + fi + fi + + # Write the line to temp file + echo "$line" >> "$temp_file" + done < "$file" + + # Replace original with cleaned version + if [ -f "$temp_file" ]; then + mv "$temp_file" "$file" + fi + + return $removed +} + +clean_input_boolean_file() { + local file="$1" + local count=0 + + print_info "Processing $(basename "$file")..." + + if [ ! -f "$file" ]; then + print_warning "File not found, skipping" + return + fi + + # Backup first + backup_file "$file" + + # Remove each input_boolean + for entity in "${INPUT_BOOLEANS_TO_REMOVE[@]}"; do + if grep -q "^[[:space:]]*${entity}:" "$file"; then + clean_yaml_entity "$file" "$entity" + if [ $? -eq 1 ]; then + ((count++)) + ((REMOVED_BOOLEANS++)) + REMOVED_BOOLEAN_NAMES+=("$entity") + fi + fi + done + + if [ $count -gt 0 ]; then + print_success "Removed $count input_boolean entries" + else + print_info "No items to remove" + fi +} + +clean_script_file() { + local file="$1" + local count=0 + + print_info "Processing $(basename "$file")..." + + if [ ! -f "$file" ]; then + print_warning "File not found, skipping" + return + fi + + # Backup first + backup_file "$file" + + # Remove each script + for entity in "${SCRIPTS_TO_REMOVE[@]}"; do + if grep -q "^[[:space:]]*${entity}:" "$file"; then + clean_yaml_entity "$file" "$entity" + if [ $? -eq 1 ]; then + ((count++)) + ((REMOVED_SCRIPTS++)) + REMOVED_SCRIPT_NAMES+=("$entity") + fi + fi + done + + if [ $count -gt 0 ]; then + print_success "Removed $count script entries" + else + print_info "No items to remove" + fi +} + +################################################################################ +# File Discovery +################################################################################ + +find_config_files() { + echo "" + print_info "Searching for configuration files..." + + # Find input_boolean files + for pattern in "input_boolean.yaml" "input_booleans.yaml" "helpers.yaml"; do + if [ -f "$CONFIG_DIR/$pattern" ]; then + clean_input_boolean_file "$CONFIG_DIR/$pattern" + fi + done + + # Check packages directory + if [ -d "$CONFIG_DIR/packages" ]; then + find "$CONFIG_DIR/packages" -name "*.yaml" -type f | while read -r file; do + # Check if file contains any of our target entities + for entity in "${INPUT_BOOLEANS_TO_REMOVE[@]}"; do + if grep -q "$entity" "$file"; then + clean_input_boolean_file "$file" + break + fi + done + done + fi + + echo "" + + # Find script files + for pattern in "scripts.yaml" "script.yaml"; do + if [ -f "$CONFIG_DIR/$pattern" ]; then + clean_script_file "$CONFIG_DIR/$pattern" + fi + done + + # Check packages directory for scripts + if [ -d "$CONFIG_DIR/packages" ]; then + find "$CONFIG_DIR/packages" -name "*.yaml" -type f | while read -r file; do + # Check if file contains any of our target entities + for entity in "${SCRIPTS_TO_REMOVE[@]}"; do + if grep -q "$entity" "$file"; then + clean_script_file "$file" + break + fi + done + done + fi +} + +################################################################################ +# Restore Script Generation +################################################################################ + +create_restore_script() { + local restore_script="$BACKUP_DIR/restore.sh" + + cat > "$restore_script" << 'EOF' +#!/bin/bash +# Restore script - Run this if you need to undo the cleanup + +echo "Restoring files from backup..." + +EOF + + # Add restore commands for each backed up file + for backup_file in "$BACKUP_DIR"/*.yaml; do + if [ -f "$backup_file" ]; then + original="$CONFIG_DIR/$(basename "$backup_file")" + echo "cp \"$backup_file\" \"$original\"" >> "$restore_script" + fi + done + + cat >> "$restore_script" << 'EOF' + +echo "" +echo "Files restored!" +echo "Please restart Home Assistant for changes to take effect" +echo "" +EOF + + chmod +x "$restore_script" + print_success "Created restore script: $restore_script" +} + +################################################################################ +# Summary Display +################################################################################ + +print_summary() { + print_header "CLEANUP SUMMARY" + + print_success "Backups saved to: $BACKUP_DIR" + + echo "" + echo "📋 Input Booleans Removed: $REMOVED_BOOLEANS" + if [ $REMOVED_BOOLEANS -gt 0 ]; then + for entity in "${REMOVED_BOOLEAN_NAMES[@]}"; do + echo " - $entity" + done + fi + + echo "" + echo "📜 Scripts Removed: $REMOVED_SCRIPTS" + if [ $REMOVED_SCRIPTS -gt 0 ]; then + for entity in "${REMOVED_SCRIPT_NAMES[@]}"; do + echo " - $entity" + done + fi + + echo "" + print_header "NEXT STEPS" + echo "1. Review the changes in your YAML files" + echo "2. Check configuration: ha core check" + echo "3. If everything looks good, restart: ha core restart" + echo "4. If issues occur, restore from: $BACKUP_DIR" + echo "5. Run restore script: bash $BACKUP_DIR/restore.sh" + echo "" + echo "======================================================================" +} + +################################################################################ +# Main Execution +################################################################################ + +main() { + print_header "Home Assistant Chore Cleanup Script (Bash)" + + # Check if config directory exists + if [ ! -d "$CONFIG_DIR" ]; then + print_error "Config directory not found: $CONFIG_DIR" + exit 1 + fi + + # Create backup directory + create_backup_dir + + # Process files + find_config_files + + # Create restore script + create_restore_script + + # Print summary + print_summary + + echo "" + print_success "Cleanup completed successfully!" + echo "" +} + +# Run main function +main