diff --git a/README.md b/README.md index a13fe1a..ddbac19 100644 --- a/README.md +++ b/README.md @@ -22,11 +22,30 @@ [![Sparkline](https://stars.medv.io/Teamultroid/Ultroid.svg)](https://stars.medv.io/TeamUltroid/Ultroid) ---- -# Deploy -- [Okteto](#deploy-to-okteto) -- [Local Machine](#deploy-locally) +# 🚀 Getting Started -# Documentation +The easiest way to set up Ultroid is by using our unified setup script. + +**Run this command in your terminal:** +```bash +bash <(curl -s https://raw.githubusercontent.com/TeamUltroid/Ultroid/main/ultroid_setup.sh) +``` +Or, clone the repository and run the script: +```bash +git clone https://github.com/TeamUltroid/Ultroid.git +cd Ultroid +bash ultroid_setup.sh +``` +This script will guide you through choosing either a Docker-based or a local Python installation and help configure the necessary variables. + +For other deployment options or more details, see below. + +# Other Deployment Options + +- [Okteto](#deploy-to-okteto) +- [Manual Setup (Docker or Local)](#manual-setup) + +# Documentation [![Documentation](https://img.shields.io/badge/Documentation-Ultroid-blue)](http://ultroid.tech/) # Tutorial @@ -40,48 +59,23 @@ Get the [Necessary Variables](#Necessary-Variables) and then click the button be [![Develop on Okteto](https://okteto.com/develop-okteto.svg)](https://cloud.okteto.com/deploy?repository=https://github.com/TeamUltroid/Ultroid) -## Deploy Locally -- [Traditional Method](#local-deploy---traditional-method) -- [Easy Method](#local-deploy---easy-method) -- [Ultroid CLI](#ultroid-cli) +## Manual Setup +If you prefer a manual setup or want to understand the components: -### Local Deploy - Easy Method -- Linux - `wget -O locals.py https://git.io/JY9UM && python3 locals.py` -- Windows - `cd desktop ; wget https://git.io/JY9UM -o locals.py ; python locals.py` -- Termux - `wget -O install-termux https://tiny.ultroid.tech/termux && bash install-termux` - -### Local Deploy - Traditional Method -- Get your [Necessary Variables](#Necessary-Variables) -- Clone the repository: -`git clone https://github.com/TeamUltroid/Ultroid.git` -- Go to the cloned folder: -`cd Ultroid` -- Create a virtual env: -`virtualenv -p /usr/bin/python3 venv` -`. ./venv/bin/activate` -- Install the requirements: -`pip(3) install -U -r re*/st*/optional-requirements.txt` -`pip(3) install -U -r requirements.txt` -- Generate your `SESSION`: - - For Linux users: - `bash sessiongen` - or - `wget -O session.py https://git.io/JY9JI && python3 session.py` - - For Termux users: - `wget -O session.py https://git.io/JY9JI && python session.py` - - For Windows Users: - `cd desktop ; wget https://git.io/JY9JI -o ultroid.py ; python ultroid.py` -- Fill your details in a `.env` file, as given in [`.env.sample`](https://github.com/TeamUltroid/Ultroid/blob/main/.env.sample). -(You can either edit and rename the file or make a new file named `.env`.) -- Run the bot: - - Linux Users: - `bash startup` - - Windows Users: - `python(3) -m pyUltroid` +* **Docker**: Refer to [DOCKER_DEPLOYMENT.md](./DOCKER_DEPLOYMENT.md) and [README_DOCKER.md](./README_DOCKER.md). The `ultroid_setup.sh` script automates this using these Docker files. +* **Local Python**: The `ultroid_setup.sh` script automates the following general steps: + 1. Clone the repository: `git clone https://github.com/TeamUltroid/Ultroid.git && cd Ultroid` + 2. Create a Python virtual environment: `python3 -m venv .venv` + 3. Activate it: `source .venv/bin/activate` + 4. Install dependencies: `pip install -r requirements.txt` + 5. Configure your variables in a `.env` file (see [Necessary Variables](#Necessary-Variables) below). + 6. Run the bot: `python3 -m pyUltroid` --- -## Necessary Variables -- `SESSION` - SessionString for your accounts login session. Get it from [here](#Session-String) +## Important: Necessary Variables +Whether using the setup script or a manual method, you will need the following: + +- **`SESSION`**: Your Telegram user account session string. The setup script and other utilities can help you generate this. See [Session String](#Session-String) for methods. One of the following database: - For **Redis** (tutorial [here](./resources/extras/redistut.md)) @@ -96,9 +90,11 @@ One of the following database: Different ways to get your `SESSION`: * [![Run on Repl.it](https://replit.com/badge/github/TeamUltroid/Ultroid)](https://replit.com/@TeamUltroid/UltroidStringSession) * Linux : `wget -O session.py https://git.io/JY9JI && python3 session.py` -* PowerShell : `cd desktop ; wget https://git.io/JY9JI ; python ultroid.py` +* PowerShell : `cd desktop ; wget https://git.io/JY9JI -OutFile session.py ; python session.py` * Termux : `wget -O session.py https://git.io/JY9JI && python session.py` -* TelegramBot : [@SessionGeneratorBot](https://t.me/SessionGeneratorBot) +* Telegram Bot : [@SessionGeneratorBot](https://t.me/SessionGeneratorBot) +* **Using `ultroid_setup.sh`**: The setup script will guide you through session generation if needed. +* **Using `generate-session.sh`**: This script in the repository provides various methods: `bash generate-session.sh` --- diff --git a/ultroid_setup.sh b/ultroid_setup.sh new file mode 100644 index 0000000..676a08f --- /dev/null +++ b/ultroid_setup.sh @@ -0,0 +1,529 @@ +#!/bin/bash + +# Script Name: ultroid_setup.sh +# Purpose: Unified setup script for Ultroid UserBot (Docker or Local Python) + +# --- Constants & Configuration --- +PYTHON_MIN_VERSION="3.9" # Minimum Python version (e.g., 3.9) +VENV_NAME=".venv" +REQUIREMENTS_FILE="requirements.txt" +ENV_SAMPLE_FILE=".env.sample" +ENV_FILE=".env" + +# Color codes for output +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' # No Color + +# --- Helper Functions --- + +_print_msg() { + type="$1" + shift + message="$*" + case "$type" in + info) echo -e "${BLUE}[INFO] $message${NC}" ;; + warn) echo -e "${YELLOW}[WARN] $message${NC}" ;; + error) echo -e "${RED}[ERROR] $message${NC}" ;; + success) echo -e "${GREEN}[SUCCESS] $message${NC}" ;; + header) echo -e "${GREEN}=== $message ===${NC}" ;; + *) echo "$message" ;; + esac +} + +_detect_os() { + os_name=$(uname -s) + case "$os_name" in + Linux*) echo "linux" ;; + Darwin*) echo "darwin" ;; + CYGWIN*) echo "windows_cygwin" ;; + MINGW*) echo "windows_mingw" ;; + *) echo "unknown:${os_name}" ;; + esac +} + +_command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +_check_python_version() { + local current_version + local required_version=$1 + local current_major current_minor required_major required_minor + + if ! _command_exists python3; then + _print_msg error "Python 3 is not installed. Please install Python $required_version or higher." + return 1 + fi + + current_version=$(python3 -V 2>&1 | awk '{print $2}') + + current_major=$(echo "$current_version" | cut -d. -f1) + current_minor=$(echo "$current_version" | cut -d. -f2) + required_major=$(echo "$required_version" | cut -d. -f1) + required_minor=$(echo "$required_version" | cut -d. -f2) + + if [ "$current_major" -lt "$required_major" ] || { [ "$current_major" -eq "$required_major" ] && [ "$current_minor" -lt "$required_minor" ]; }; then + _print_msg error "Python version $current_version is installed. Ultroid requires Python $required_version or higher." + return 1 + fi + _print_msg success "Python version $current_version found." + return 0 +} + +_prompt_user() { + local prompt_message="$1" + local var_name="$2" + local default_value="${3:-}" # Use bash specific default value assignment + local current_value="${!var_name:-$default_value}" # Get current value of var_name or default + local input + + if [ -n "$default_value" ]; then + read -p "$(echo -e "${YELLOW}$prompt_message${NC} [Default: $default_value]: ")" input + else + read -p "$(echo -e "${YELLOW}$prompt_message${NC}: ")" input + fi + + if [ -z "$input" ] && [ -n "$default_value" ]; then + eval "$var_name=\"$default_value\"" + else + eval "$var_name=\"$input\"" + fi +} + +_prompt_user_sensitive() { + local prompt_message="$1" + local var_name="$2" + local input + + read -sp "$(echo -e "${YELLOW}$prompt_message${NC}: ")" input + echo # Newline after sensitive input + eval "$var_name=\"$input\"" +} + + +# --- Prerequisite Checks --- +_check_prerequisites() { + _print_msg header "Checking Prerequisites" + local all_ok=true + + if _command_exists git; then + _print_msg success "Git is installed." + else + _print_msg error "Git is not installed. Please install Git and re-run the script." + # Add OS-specific install instructions here if desired + all_ok=false + fi + + if _check_python_version "$PYTHON_MIN_VERSION"; then + # Success message already printed by _check_python_version + if _command_exists pip3; then + _print_msg success "pip3 is available." + elif _command_exists pip; then + _print_msg success "pip is available (will assume it's for Python 3)." + else + _print_msg error "pip for Python 3 is not installed. Please install pip." + all_ok=false + fi + else + all_ok=false + fi + + if [ "$all_ok" = false ]; then + _print_msg error "One or more prerequisites are missing. Please install them and try again." + exit 1 + fi +} + +# --- Environment Variable Collection --- +_collect_env_variables() { + _print_msg header "Collecting Environment Variables" + + if [ -f "$ENV_FILE" ]; then + _print_msg info "$ENV_FILE already exists." + read -p "Do you want to (o)verwrite, (u)pdate missing values, or (s)kip? [o/u/s, default: u]: " env_action + env_action=${env_action:-u} + else + _print_msg info "Creating a new $ENV_FILE." + cp "$ENV_SAMPLE_FILE" "$ENV_FILE" # Start with sample if it exists and target doesn't + env_action="new" + fi + + # Define an associative array for defaults and comments if needed for complex logic + # For now, direct prompts. Load existing values if updating. + declare -A existing_env_vars + if [ "$env_action" = "u" ] && [ -f "$ENV_FILE" ]; then + while IFS='=' read -r key value; do + # Remove potential surrounding quotes from value + value="${value%\"}" + value="${value#\"}" + value="${value%\'}" + value="${value#\'}" + existing_env_vars["$key"]="$value" + done < <(grep -v '^#' "$ENV_FILE" | grep '=') # Read non-commented lines with '=' + elif [ "$env_action" = "o" ]; then + > "$ENV_FILE" # Clear the file if overwriting + fi + + # Helper to get existing or default for prompt + _get_val() { echo "${existing_env_vars[$1]:-$2}"; } + + API_ID=$(_get_val "API_ID") + _prompt_user "Enter your API_ID (from my.telegram.org/apps)" API_ID "$API_ID" + + API_HASH=$(_get_val "API_HASH") + _prompt_user_sensitive "Enter your API_HASH (from my.telegram.org/apps)" API_HASH + + SESSION=$(_get_val "SESSION") + _prompt_user_sensitive "Enter your SESSION string (Leave blank to generate/get instructions later)" SESSION "$SESSION" + + BOT_TOKEN=$(_get_val "BOT_TOKEN") + _prompt_user_sensitive "Enter your BOT_TOKEN (Optional, from @BotFather)" BOT_TOKEN "$BOT_TOKEN" + + LOG_CHANNEL=$(_get_val "LOG_CHANNEL" "0") + _prompt_user "Enter your LOG_CHANNEL ID (Numeric, e.g., -100xxxxxxxx or your User ID)" LOG_CHANNEL "$LOG_CHANNEL" + + OWNER_ID=$(_get_val "OWNER_ID") + _prompt_user "Enter your OWNER_ID (Your numeric Telegram User ID)" OWNER_ID "$OWNER_ID" + + # Database choice + DATABASE_TYPE=$(_get_val "DATABASE_TYPE" "redis") # redis, mongo, sql, local + _print_msg info "Choose your database type:" + echo "1. Redis (Recommended for Docker, requires Redis server)" + echo "2. MongoDB (Requires MongoDB server)" + echo "3. PostgreSQL (Requires PostgreSQL server)" + echo "4. Local File DB (Simple, no external server needed, default if others unset)" + read -p "Select database (1-4, default: 1 for Redis if Docker, 4 for Local if not Docker): " db_choice_num + + # Default db_choice_num based on setup type will be handled later + # For now, let's assume default is redis for this collection part. + + case "$db_choice_num" in + 1) DATABASE_TYPE="redis" ;; + 2) DATABASE_TYPE="mongo" ;; + 3) DATABASE_TYPE="sql" ;; + 4) DATABASE_TYPE="local" ;; + *) _print_msg warn "Invalid database choice, defaulting to 'redis' for now. This will be refined." + DATABASE_TYPE="redis" ;; # Default or re-prompt later + esac + + REDIS_URI=$(_get_val "REDIS_URI") + REDIS_PASSWORD=$(_get_val "REDIS_PASSWORD") + MONGO_URI=$(_get_val "MONGO_URI") + DATABASE_URL=$(_get_val "DATABASE_URL") # For SQL + + if [ "$DATABASE_TYPE" = "redis" ]; then + _prompt_user "Enter REDIS_URI (e.g., redis://localhost:6379)" REDIS_URI "$REDIS_URI" + _prompt_user_sensitive "Enter REDIS_PASSWORD (if any)" REDIS_PASSWORD "$REDIS_PASSWORD" + MONGO_URI="" # Clear other DB vars + DATABASE_URL="" + elif [ "$DATABASE_TYPE" = "mongo" ]; then + _prompt_user "Enter MONGO_URI (e.g., mongodb://user:pass@host:port/dbname)" MONGO_URI "$MONGO_URI" + REDIS_URI="" + REDIS_PASSWORD="" + DATABASE_URL="" + elif [ "$DATABASE_TYPE" = "sql" ]; then + _prompt_user "Enter DATABASE_URL (PostgreSQL, e.g., postgresql://user:pass@host:port/dbname)" DATABASE_URL "$DATABASE_URL" + REDIS_URI="" + REDIS_PASSWORD="" + MONGO_URI="" + else # local + REDIS_URI="" + REDIS_PASSWORD="" + MONGO_URI="" + DATABASE_URL="" + fi + + TZ=$(_get_val "TZ" "Asia/Kolkata") + _prompt_user "Enter your Timezone (e.g., Asia/Kolkata, Europe/London)" TZ "$TZ" + + # Write to .env file + # This is a simple overwrite. A more sophisticated approach would update existing values. + { + echo "API_ID=${API_ID}" + echo "API_HASH=${API_HASH}" + echo "SESSION=${SESSION}" + echo "BOT_TOKEN=${BOT_TOKEN}" + echo "LOG_CHANNEL=${LOG_CHANNEL}" + echo "OWNER_ID=${OWNER_ID}" + echo "TZ=${TZ}" + if [ "$DATABASE_TYPE" = "redis" ]; then + echo "REDIS_URI=${REDIS_URI}" + echo "REDIS_PASSWORD=${REDIS_PASSWORD}" + elif [ "$DATABASE_TYPE" = "mongo" ]; then + echo "MONGO_URI=${MONGO_URI}" + elif [ "$DATABASE_TYPE" = "sql" ]; then + echo "DATABASE_URL=${DATABASE_URL}" + fi + # Add other common optional vars from .env.sample here, prompting if desired + echo "VCBOT=False" # Example default optional + echo "ADDONS=False" # Example default optional + } > "$ENV_FILE" + + _print_msg success "$ENV_FILE has been configured." +} + +# --- Main Script Logic --- +main() { + _print_msg header "Welcome to the Ultroid UserBot Setup Script!" + echo "This script will guide you through setting up Ultroid either using Docker or a local Python environment." + echo "-----------------------------------------------------" + + # Ensure script is run from project root or can find its files + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" &>/dev/null && pwd)" + if [ ! -f "$SCRIPT_DIR/$ENV_SAMPLE_FILE" ]; then + _print_msg error "Could not find $ENV_SAMPLE_FILE. Make sure you are running the script from the Ultroid project root." + # exit 1 # Potentially allow to continue if user creates .env manually + else + cd "$SCRIPT_DIR" # Change to script's directory (project root) + fi + + + DETECTED_OS=$(_detect_os) + _print_msg info "Detected OS: $DETECTED_OS" + + _check_prerequisites + + echo "-----------------------------------------------------" + echo "Choose your setup method:" + echo "1. Docker (Recommended for isolated environment)" + echo "2. Local Python (Requires Python $PYTHON_MIN_VERSION or higher)" + read -p "Enter your choice (1 or 2): " setup_choice + echo "-----------------------------------------------------" + + # Placeholder for setup functions will be replaced below + # _setup_docker() { _print_msg info "Docker setup chosen (Not yet implemented fully)."; _collect_env_variables; } + # _setup_local_python() { _print_msg info "Local Python setup chosen (Not yet implemented fully)."; _collect_env_variables; } + +_generate_session_docker() { + _print_msg info "Attempting to generate session string using Docker..." + if [ ! -f "docker-compose.yml" ]; then + _print_msg error "docker-compose.yml not found. Cannot generate session with Docker." + return 1 + fi + + # Ensure session_output directory exists and is writable (Docker user might need this) + mkdir -p session_output + # The Dockerfile now runs as non-root 'ultroid'. + # The session_output volume in docker-compose.yml is /home/ultroid/app/session_output + # We need to ensure the host ./session_output is writable by this user if it's a new mount. + # Or, the script inside container should handle permissions if it creates files as root then copies. + # The current session-gen command `cp *.session session_output/` should work if session_output is WORKDIR/session_output + + _print_msg info "Running Docker session generator. Please follow the prompts." + _print_msg warn "You will be asked for your API_ID, API_HASH, and phone number by the Telethon script." + + # Temporarily ensure API_ID and API_HASH are available for the session generator container if it needs them from .env + # The generate-session.sh script's Docker method runs a generic python image with Telethon. + # The docker-compose profile "session-gen" uses the main Dockerfile. + # The command `wget -O session.py ... && python3 session.py` does not directly use .env API_ID/HASH. + # It prompts for them. + + if docker-compose --profile session run --rm session-gen; then + _print_msg success "Session generation process completed." + _print_msg info "If successful, your session string was printed to the console and saved in ./session_output." + _print_msg warn "Please copy the SESSION string from the output above (it's a long string)." + _prompt_user_sensitive "Paste the generated SESSION string here" SESSION_FROM_GEN + if [ -n "$SESSION_FROM_GEN" ]; then + _update_env_var "SESSION" "$SESSION_FROM_GEN" "$ENV_FILE" + _print_msg success "SESSION string updated in $ENV_FILE." + return 0 + else + _print_msg error "No session string was pasted. You might need to run session generation again or enter it manually." + return 1 + fi + else + _print_msg error "Docker session generation failed." + return 1 + fi +} + +_generate_session_if_needed() { + local session_val + session_val=$(grep "^SESSION=" "$ENV_FILE" | cut -d'=' -f2-) + + if [ -n "$session_val" ]; then + _print_msg info "SESSION string already found in $ENV_FILE." + return 0 + fi + + _print_msg warn "SESSION string is missing." + echo "How would you like to provide the SESSION string?" + echo "1. Enter manually" + echo "2. Generate using Docker (if you chose Docker setup)" + echo "3. Get instructions for @SessionGeneratorBot (Telegram Bot)" + read -p "Choose an option [1/2/3, default: 1]: " session_choice + session_choice=${session_choice:-1} + + case "$session_choice" in + 1) + _prompt_user_sensitive "Please enter your SESSION string" NEWSESSION + if [ -n "$NEWSESSION" ]; then + _update_env_var "SESSION" "$NEWSESSION" "$ENV_FILE" + _print_msg success "SESSION string updated in $ENV_FILE." + else + _print_msg error "No session string entered. Setup might fail." + return 1 + fi + ;; + 2) + # This option should only be presented if Docker setup was chosen. + # We'll call this function from within _setup_docker or _setup_local_python + # So, the caller should ensure this option is valid. + # For now, assume it's called from _setup_docker + if [ "$SETUP_TYPE" = "docker" ]; then + _generate_session_docker || return 1 + else + _print_msg error "Docker session generation is only available if you chose Docker setup." + _print_msg info "Please choose another method or restart and select Docker setup." + return 1 + fi + ;; + 3) + _print_msg info "To generate a session string using a Telegram bot:" + _print_msg info "1. Go to @SessionGeneratorBot on Telegram." + _print_msg info "2. Follow the bot's instructions." + _print_msg info "3. Copy the session string provided by the bot." + _prompt_user_sensitive "Once you have the SESSION string, please paste it here" NEWSESSION + if [ -n "$NEWSESSION" ]; then + _update_env_var "SESSION" "$NEWSESSION" "$ENV_FILE" + _print_msg success "SESSION string updated in $ENV_FILE." + else + _print_msg error "No session string entered. Setup might fail." + return 1 + fi + ;; + *) + _print_msg error "Invalid choice for session string." + return 1 + ;; + esac + return 0 +} + + +_setup_docker() { + _print_msg header "Starting Docker Setup" + SETUP_TYPE="docker" # Set context for _generate_session_if_needed + + if ! _command_exists docker; then + _print_msg error "Docker is not installed. Please install Docker and re-run." + # Add more specific guidance based on OS if possible + _print_msg info "Installation guide: https://docs.docker.com/engine/install/" + exit 1 + fi + _print_msg success "Docker is installed." + + if ! _command_exists docker-compose && ! docker compose version &>/dev/null; then + _print_msg error "Docker Compose is not installed. Please install Docker Compose and re-run." + _print_msg info "Installation guide: https://docs.docker.com/compose/install/" + exit 1 + fi + _print_msg success "Docker Compose is installed." + + # Ensure Dockerfile and docker-compose.yml are present + if [ ! -f "Dockerfile" ] || [ ! -f "docker-compose.yml" ]; then + _print_msg error "Dockerfile or docker-compose.yml not found. Ensure you are in the project root." + exit 1 + fi + + # Check if .env.sample exists before calling _collect_env_variables + if [ ! -f "$ENV_SAMPLE_FILE" ]; then + _print_msg error "$ENV_SAMPLE_FILE not found. Cannot proceed with environment configuration." + exit 1 + fi + _collect_env_variables || { _print_msg error "Failed to configure environment variables."; exit 1; } + + _generate_session_if_needed || { _print_msg error "Session string configuration failed. Please ensure SESSION is set in $ENV_FILE."; exit 1; } + + _print_msg info "Building Docker image(s). This may take some time..." + if docker-compose build; then + _print_msg success "Docker image(s) built successfully." + else + _print_msg error "Docker image build failed. Please check the output above for errors." + exit 1 + fi + + _print_msg info "Starting Ultroid services using Docker Compose..." + if docker-compose up -d; then + _print_msg success "Ultroid services started successfully in detached mode." + _print_msg info "You can check the logs using: docker-compose logs -f ultroid" + _print_msg info "To stop the services, run: docker-compose down" + else + _print_msg error "Failed to start Ultroid services. Check 'docker-compose logs ultroid' for details." + exit 1 + fi +} + +_setup_local_python() { + _print_msg header "Starting Local Python Setup"; + SETUP_TYPE="local" + + # Check Python version again specifically for this path + if ! _check_python_version "$PYTHON_MIN_VERSION"; then + exit 1 + fi + + # Check if .env.sample exists + if [ ! -f "$ENV_SAMPLE_FILE" ]; then + _print_msg error "$ENV_SAMPLE_FILE not found. Cannot proceed." + exit 1 + fi + _collect_env_variables || { _print_msg error "Failed to configure environment variables."; exit 1; } + + # For local Python, session generation via Docker is not an option unless Docker is also installed. + # _generate_session_if_needed will handle prompting. + # Modify _generate_session_if_needed to not offer Docker option if SETUP_TYPE="local" + _generate_session_if_needed || { _print_msg error "Session string configuration failed."; exit 1; } + + _print_msg info "Creating Python virtual environment in '$VENV_NAME'..." + if python3 -m venv "$VENV_NAME"; then + _print_msg success "Virtual environment created." + else + _print_msg error "Failed to create virtual environment." + exit 1 + fi + + _print_msg info "Activating virtual environment and installing dependencies..." + _print_msg warn "This may take a significant amount of time." + # shellcheck source=/dev/null + if source "${VENV_NAME}/bin/activate" && pip install -r "$REQUIREMENTS_FILE"; then + _print_msg success "Dependencies installed successfully." + else + _print_msg error "Failed to install dependencies. Check for errors above." + _print_msg info "You might need to manually activate the venv: 'source $VENV_NAME/bin/activate' and then run 'pip install -r $REQUIREMENTS_FILE'." + exit 1 + fi + + # Deactivate might not be strictly necessary here as script ends, but good practice + # Or inform user how to deactivate. For now, leave it active for them to run. + + _print_msg success "Local Python setup complete!" + _print_msg info "To run Ultroid:" + _print_msg info "1. If not already active, activate the virtual environment: source $VENV_NAME/bin/activate" + _print_msg info "2. Start Ultroid: python3 -m pyUltroid" + _print_msg info "To deactivate the virtual environment later, simply type: deactivate" +} + + + case $setup_choice in + 1) + _setup_docker + ;; + 2) + _setup_local_python + ;; + *) + _print_msg error "Invalid choice. Exiting." + exit 1 + ;; + esac + + _print_msg success "Ultroid setup process finished." + _print_msg info "Please review any specific instructions above for your chosen setup type." +} + +# --- Entry Point --- +main