- 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
374 lines
10 KiB
Bash
374 lines
10 KiB
Bash
#!/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
|