#!/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