#!/bin/bash set -euo pipefail # Constants readonly DC="docker compose -f -f " readonly INSTALL_DIRECTORY="" readonly TIMEOUT_SECONDS=60 readonly IP_ENDPOINTS=( "https://ipinfo.io/ip" "https://api.ipify.org" "https://checkip.amazonaws.com" "https://tnedi.me" "https://api.myip.la" "https://wtfismyip.com/text" ) # Color codes for better readability readonly RED='\033[0;31m' readonly GREEN='\033[0;32m' readonly YELLOW='\033[1;33m' readonly NC='\033[0m' # No Color # Available commands declare -A COMMANDS=( ["--help"]="displays this help message" ["restart"]="restarts yams services" ["stop"]="stops all yams services" ["start"]="starts yams services" ["destroy"]="destroy yams services so you can start from scratch" ["check-vpn"]="checks if the VPN is working as expected" ["backup"]="backs up yams to the destination location" ) # Functions log_success() { echo -e "${GREEN}$1${NC}" } log_error() { echo -e "${RED}$1${NC}" >&2 exit 1 } log_warning() { echo -e "${YELLOW}$1${NC}" } show_help() { echo "yams - Yet Another Media Server" echo echo "Usage: yams [command] [options]" echo echo "Commands:" for cmd in "${!COMMANDS[@]}"; do printf "%-25s %s\n" "$cmd" "${COMMANDS[$cmd]}" done echo echo "Examples:" echo " yams start # Start all YAMS services" echo " yams backup /path/to/backup # Backup YAMS to specified directory" } wait_for_services() { local wait_time=0 echo -n "Waiting for services to start" while [ $wait_time -lt $TIMEOUT_SECONDS ]; do # Get the total number of services and number of running services local total_services local running_services total_services=$($DC ps --format '{{.Name}}' | wc -l) running_services=$($DC ps --format '{{.Status}}' | grep -c "Up") if [ "$total_services" -eq "$running_services" ]; then echo log_success "All $total_services services are up and running!" return 0 fi # Show progress with count echo -n "." sleep 1 ((wait_time++)) # Every 10 seconds, show status if [ $((wait_time % 10)) -eq 0 ]; then echo echo -n "$running_services/$total_services services running" fi done echo log_error "Not all services started within ${TIMEOUT_SECONDS} seconds ($running_services/$total_services running)" } find_available_ip_endpoint() { for endpoint in "${IP_ENDPOINTS[@]}"; do if curl -s --connect-timeout 5 "$endpoint" > /dev/null; then echo "$endpoint" return 0 fi done return 1 } get_ip_with_retries() { local context=$1 # "local" or "qbittorrent" local cmd_prefix="" if [ "$context" = "qbittorrent" ]; then cmd_prefix="docker exec qbittorrent" fi for endpoint in "${IP_ENDPOINTS[@]}"; do local ip if [ "$context" = "local" ]; then ip=$(curl -s --connect-timeout 5 "$endpoint") else ip=$($cmd_prefix curl -s --connect-timeout 5 "$endpoint") fi if [ -n "$ip" ] && [[ "$ip" =~ ^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$ ]]; then echo "$ip" return 0 fi done return 1 } check_vpn() { echo "Getting your IP..." local your_ip your_ip=$(get_ip_with_retries "local") || log_error "Failed to get your IP address from any endpoint" echo "Your IP: $your_ip" local country country=$(curl -s --connect-timeout 5 "https://am.i.mullvad.net/country") || log_warning "Couldn't determine your country" [ -n "$country" ] && echo "Your local IP country is $country" echo -e "\nGetting your qBittorrent IP..." local qbit_ip qbit_ip=$(get_ip_with_retries "qbittorrent") || log_error "Failed to get qBittorrent IP from any endpoint" echo "qBittorrent IP: $qbit_ip" local qbit_country qbit_country=$(docker exec qbittorrent curl -s --connect-timeout 5 "https://am.i.mullvad.net/country") || log_warning "Couldn't determine qBittorrent country" [ -n "$qbit_country" ] && echo "qBittorrent country is $qbit_country" if [ "$qbit_ip" == "$your_ip" ]; then log_error "⚠️ WARNING: Your IPs are the same! qBittorrent is exposing your IP!" else log_success "✅ Success: Your IPs are different. qBittorrent is masking your IP!" fi } backup_yams() { local destination=$1 local backup_date backup_date=$(date '+%Y-%m-%d-%s') local backup_file="$destination/yams-backup-$backup_date.tar.gz" echo "Stopping YAMS services..." $DC stop > /dev/null 2>&1 || log_error "Failed to stop services" echo -e "\nBacking up YAMS to $destination..." echo "This may take a while depending on the size of your installation." echo "Please wait... ⌛" # Copy current yams script and create backup cp "$(which yams)" "$INSTALL_DIRECTORY" || log_warning "Failed to backup yams script" tar --exclude='transcoding-temp' -czf "$backup_file" -C "$INSTALL_DIRECTORY" . || log_error "Failed to create backup archive" echo -e "\nStarting YAMS services..." $DC start > /dev/null 2>&1 || log_warning "Failed to restart services" log_success "Backup completed successfully! 🎉" echo "Backup file: $backup_file" } destroy_yams() { echo -e "\nWARNING: This will destroy all your YAMS services!" read -p "Are you sure you want to continue? This is not recoverable! ⚠️ 🚨 [y/N]: " -r if [[ ${REPLY,,} =~ ^y$ ]]; then $DC down || log_error "Failed to destroy services" echo -e "\nYAMS services were destroyed. To restart, run: yams start" fi } main() { local command=${1:-"--help"} local destination=${2:-.} # Validate and normalize destination path if provided if [ "$command" = "backup" ]; then destination=$(realpath "$destination") || log_error "Invalid backup destination path" fi case "$command" in --help) show_help ;; restart) $DC stop && $DC up -d wait_for_services ;; stop) $DC stop || log_error "Failed to stop services" log_success "Services stopped successfully" ;; start) $DC up -d || log_error "Failed to start services" wait_for_services ;; check-vpn) check_vpn ;; destroy) destroy_yams ;; backup) backup_yams "$destination" ;; *) log_error "Unknown command: $command\nRun 'yams --help' for usage information" ;; esac } main "$@"