From c69028a970b4130c22aea91dd4e448ddf3bebe01 Mon Sep 17 00:00:00 2001
From: Spencer Grimes <toamidan@gmail.com>
Date: Sun, 18 Jan 2026 17:30:15 -0600
Subject: [PATCH] docs: Update README and add Linux setup script

Improve documentation and add a setup script for easy deployment on Linux systems.

- Update README.md with instructions for the new multi-voice slash commands and the oices/ directory structure.
- Add a comprehensive 'Linux Server Deployment' section to the README, detailing both a quick setup via a new script and a manual systemd service setup.
- Create setup_linux.sh to automate dependency checking, virtual environment creation, and service installation on Linux.
- Revise comments in .env.example for clarity and to reflect the latest configuration options.
---
 .env.example   |  19 +++--
 README.md      | 113 ++++++++++++++++++++++++--
 setup_linux.sh | 213 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 333 insertions(+), 12 deletions(-)
 create mode 100644 setup_linux.sh

diff --git a/.env.example b/.env.example
index 87ddf19..d838b93 100644
--- a/.env.example
+++ b/.env.example
@@ -1,9 +1,16 @@
-# Discord Bot Token (from Discord Developer Portal)
-DISCORD_TOKEN=your_discord_bot_token_here
+# Discord Bot Configuration
+# Copy this file to .env and fill in your values
 
-# Channel ID to monitor for TTS messages
-# Right-click the channel in Discord and copy ID (enable Developer Mode in settings)
+# Your Discord bot token (from Discord Developer Portal)
+DISCORD_TOKEN=your_bot_token_here
+
+# The text channel ID to monitor for messages
+# (Right-click channel with Developer Mode enabled -> Copy ID)
 TEXT_CHANNEL_ID=123456789012345678
 
-# Path to the voice reference WAV file for voice cloning
-VOICE_WAV_PATH=./voice.wav
+# Directory containing voice .wav files
+VOICES_DIR=./voices
+
+# Default voice name (optional - uses first found voice if not set)
+# This should match the filename without .wav extension (case-insensitive)
+# DEFAULT_VOICE=masterchief
diff --git a/README.md b/README.md
index a139090..527ea22 100644
--- a/README.md
+++ b/README.md
@@ -8,6 +8,9 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky
 - 📝 **Auto-read Messages**: Automatically reads all messages from a configured text channel
 - 🔊 **Voice Channel Streaming**: Streams generated audio to the voice channel where the message author is
 - 📋 **Message Queue**: Messages are queued and spoken in order
+- 🔄 **Per-User Voice Selection**: Each user can choose their own TTS voice via `/voice` commands
+- 💾 **Voice Persistence**: User voice preferences are saved and restored on restart
+- 🔄 **Hot-reload Voices**: Add new voices without restarting the bot using `/voice refresh`
 
 ## Prerequisites
 
@@ -75,12 +78,15 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky
    ```env
    DISCORD_TOKEN=your_bot_token_here
    TEXT_CHANNEL_ID=123456789012345678
-   VOICE_WAV_PATH=./voice.wav
+   VOICES_DIR=./voices
+   DEFAULT_VOICE=estinien
    ```
 
-5. **Add a voice reference file**:
-   - Place a WAV file named `voice.wav` in the project directory
-   - The file should contain 3-10 seconds of clear speech
+5. **Add voice reference files**:
+   - Create a `voices/` directory: `mkdir voices`
+   - Place `.wav` files in the `voices/` directory
+   - Each file should contain 3-10 seconds of clear speech
+   - File names become voice names (e.g., `MasterChief.wav` → `/voice set masterchief`)
    - Higher quality audio = better voice cloning results
 
 ## Usage
@@ -96,6 +102,12 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky
    - The bot will join your voice channel and read your message aloud
    - Messages are queued if the bot is already speaking
 
+3. **Voice Commands** (Slash Commands):
+   - `/voice list` - Shows all available voices
+   - `/voice set <name>` - Change your personal TTS voice
+   - `/voice current` - Shows your current voice
+   - `/voice refresh` - Re-scan for new voice files (no restart needed)
+
 ## How It Works
 
 ```
@@ -106,8 +118,8 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky
                               ▲
                               │
                         ┌─────┴─────┐
-                        │ voice.wav │
-                        │ (speaker) │
+                        │  voices/  │
+                        │ per-user  │
                         └───────────┘
 ```
 
@@ -133,6 +145,95 @@ A Discord bot that reads messages aloud using [Pocket TTS](https://github.com/ky
 - Ensure the reference audio is clear with minimal background noise
 - Try a longer reference clip (5-10 seconds)
 
+## Linux Server Deployment
+
+To run the bot as a service on a Linux server:
+
+### Quick Setup (Recommended)
+
+```bash
+# Make the setup script executable
+chmod +x setup_linux.sh
+
+# Run the setup script
+./setup_linux.sh
+```
+
+The script will:
+- Check system dependencies (Python 3.10+, FFmpeg, pip)
+- Create a virtual environment and install dependencies
+- Create `.env` template if needed
+- Optionally install and configure the systemd service
+
+### Manual Setup
+
+1. **Install system dependencies**:
+   ```bash
+   # Ubuntu/Debian
+   sudo apt update
+   sudo apt install python3 python3-pip python3-venv ffmpeg
+   
+   # Fedora
+   sudo dnf install python3 python3-pip ffmpeg
+   
+   # Arch
+   sudo pacman -S python python-pip ffmpeg
+   ```
+
+2. **Set up the project**:
+   ```bash
+   cd /path/to/PocketTTSBot
+   python3 -m venv venv
+   source venv/bin/activate
+   pip install -r requirements.txt
+   ```
+
+3. **Configure the service**:
+   
+   Edit `pockettts.service` and replace:
+   - `YOUR_USERNAME` with your Linux username
+   - Update paths if your bot is not in `/home/YOUR_USERNAME/PocketTTSBot`
+
+4. **Install the service**:
+   ```bash
+   sudo cp pockettts.service /etc/systemd/system/
+   sudo systemctl daemon-reload
+   sudo systemctl enable pockettts  # Start on boot
+   sudo systemctl start pockettts   # Start now
+   ```
+
+### Service Management
+
+```bash
+# Check status
+sudo systemctl status pockettts
+
+# View logs (live)
+journalctl -u pockettts -f
+
+# View recent logs
+journalctl -u pockettts --since "1 hour ago"
+
+# Restart after changes
+sudo systemctl restart pockettts
+
+# Stop the bot
+sudo systemctl stop pockettts
+
+# Disable auto-start
+sudo systemctl disable pockettts
+```
+
+### Updating the Bot
+
+```bash
+cd /path/to/PocketTTSBot
+git pull  # If using git
+source venv/bin/activate
+pip install -r requirements.txt
+sudo systemctl restart pockettts
+```
+
 ## License
 
 MIT License
diff --git a/setup_linux.sh b/setup_linux.sh
new file mode 100644
index 0000000..e6b5aef
--- /dev/null
+++ b/setup_linux.sh
@@ -0,0 +1,213 @@
+#!/bin/bash
+
+# Pocket TTS Discord Bot - Linux Setup Script
+# This script helps set up the bot and install it as a systemd service
+
+set -e
+
+# Colors for output
+RED='\033[0;31m'
+GREEN='\033[0;32m'
+YELLOW='\033[1;33m'
+NC='\033[0m' # No Color
+
+echo -e "${GREEN}========================================${NC}"
+echo -e "${GREEN}  Pocket TTS Discord Bot - Linux Setup${NC}"
+echo -e "${GREEN}========================================${NC}"
+echo
+
+# Get the directory where this script is located
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+USERNAME="$(whoami)"
+
+# Check if running as root
+if [ "$EUID" -eq 0 ]; then
+    echo -e "${RED}Please do not run this script as root.${NC}"
+    echo "Run it as the user who will own the bot."
+    exit 1
+fi
+
+# Function to check if a command exists
+command_exists() {
+    command -v "$1" >/dev/null 2>&1
+}
+
+echo -e "${YELLOW}Step 1: Checking system dependencies...${NC}"
+
+# Check for Python 3.10+
+if command_exists python3; then
+    PYTHON_VERSION=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")')
+    PYTHON_MAJOR=$(echo $PYTHON_VERSION | cut -d. -f1)
+    PYTHON_MINOR=$(echo $PYTHON_VERSION | cut -d. -f2)
+    
+    if [ "$PYTHON_MAJOR" -ge 3 ] && [ "$PYTHON_MINOR" -ge 10 ]; then
+        echo -e "  ${GREEN}✓${NC} Python $PYTHON_VERSION found"
+    else
+        echo -e "  ${RED}✗${NC} Python 3.10+ required, found $PYTHON_VERSION"
+        echo "  Please install Python 3.10 or later"
+        exit 1
+    fi
+else
+    echo -e "  ${RED}✗${NC} Python 3 not found"
+    echo "  Please install Python 3.10 or later"
+    exit 1
+fi
+
+# Check for FFmpeg
+if command_exists ffmpeg; then
+    FFMPEG_VERSION=$(ffmpeg -version 2>&1 | head -n1 | cut -d' ' -f3)
+    echo -e "  ${GREEN}✓${NC} FFmpeg found ($FFMPEG_VERSION)"
+else
+    echo -e "  ${RED}✗${NC} FFmpeg not found"
+    echo ""
+    echo "  Please install FFmpeg:"
+    echo "    Ubuntu/Debian: sudo apt install ffmpeg"
+    echo "    Fedora: sudo dnf install ffmpeg"
+    echo "    Arch: sudo pacman -S ffmpeg"
+    exit 1
+fi
+
+# Check for pip
+if command_exists pip3; then
+    echo -e "  ${GREEN}✓${NC} pip3 found"
+else
+    echo -e "  ${RED}✗${NC} pip3 not found"
+    echo "  Please install python3-pip"
+    exit 1
+fi
+
+echo
+echo -e "${YELLOW}Step 2: Setting up virtual environment...${NC}"
+
+cd "$SCRIPT_DIR"
+
+if [ -d "venv" ]; then
+    echo "  Virtual environment already exists"
+else
+    echo "  Creating virtual environment..."
+    python3 -m venv venv
+    echo -e "  ${GREEN}✓${NC} Virtual environment created"
+fi
+
+echo "  Activating virtual environment..."
+source venv/bin/activate
+
+echo "  Installing dependencies..."
+pip install --upgrade pip -q
+pip install -r requirements.txt -q
+echo -e "  ${GREEN}✓${NC} Dependencies installed"
+
+echo
+echo -e "${YELLOW}Step 3: Checking configuration...${NC}"
+
+# Check for .env file
+if [ -f ".env" ]; then
+    echo -e "  ${GREEN}✓${NC} .env file found"
+else
+    echo -e "  ${YELLOW}!${NC} .env file not found"
+    echo "  Creating .env template..."
+    cat > .env << 'EOF'
+# Discord Bot Configuration
+DISCORD_TOKEN=your_bot_token_here
+TEXT_CHANNEL_ID=your_channel_id_here
+
+# Voice Configuration
+VOICES_DIR=./voices
+# DEFAULT_VOICE=estinien
+EOF
+    echo -e "  ${YELLOW}!${NC} Please edit .env with your Discord token and channel ID"
+fi
+
+# Check for voices directory
+if [ -d "voices" ]; then
+    VOICE_COUNT=$(find voices -name "*.wav" 2>/dev/null | wc -l)
+    echo -e "  ${GREEN}✓${NC} voices directory found ($VOICE_COUNT voice files)"
+    if [ "$VOICE_COUNT" -eq 0 ]; then
+        echo -e "  ${YELLOW}!${NC} No voice files found. Add .wav files to the voices directory."
+    fi
+else
+    echo "  Creating voices directory..."
+    mkdir -p voices
+    echo -e "  ${YELLOW}!${NC} Add voice .wav files to the voices directory"
+fi
+
+echo
+echo -e "${YELLOW}Step 4: Setting up systemd service...${NC}"
+
+read -p "Do you want to install the bot as a systemd service? (y/n) " -n 1 -r
+echo
+if [[ $REPLY =~ ^[Yy]$ ]]; then
+    # Create the service file with correct paths
+    SERVICE_FILE="/tmp/pockettts.service"
+    
+    cat > "$SERVICE_FILE" << EOF
+[Unit]
+Description=Pocket TTS Discord Bot
+After=network-online.target
+Wants=network-online.target
+
+[Service]
+User=$USERNAME
+Group=$USERNAME
+WorkingDirectory=$SCRIPT_DIR
+ExecStart=$SCRIPT_DIR/venv/bin/python bot.py
+Restart=on-failure
+RestartSec=10
+TimeoutStopSec=30
+StandardOutput=journal
+StandardError=journal
+SyslogIdentifier=pockettts
+
+# Security hardening
+NoNewPrivileges=true
+ProtectSystem=strict
+ProtectHome=read-only
+ReadWritePaths=$SCRIPT_DIR/voices
+PrivateTmp=true
+
+[Install]
+WantedBy=multi-user.target
+EOF
+
+    echo "  Installing systemd service (requires sudo)..."
+    sudo cp "$SERVICE_FILE" /etc/systemd/system/pockettts.service
+    sudo systemctl daemon-reload
+    echo -e "  ${GREEN}✓${NC} Service installed"
+    
+    read -p "Do you want to enable the service to start on boot? (y/n) " -n 1 -r
+    echo
+    if [[ $REPLY =~ ^[Yy]$ ]]; then
+        sudo systemctl enable pockettts
+        echo -e "  ${GREEN}✓${NC} Service enabled for boot"
+    fi
+    
+    read -p "Do you want to start the service now? (y/n) " -n 1 -r
+    echo
+    if [[ $REPLY =~ ^[Yy]$ ]]; then
+        sudo systemctl start pockettts
+        echo -e "  ${GREEN}✓${NC} Service started"
+        sleep 2
+        echo
+        echo "  Service status:"
+        sudo systemctl status pockettts --no-pager || true
+    fi
+fi
+
+echo
+echo -e "${GREEN}========================================${NC}"
+echo -e "${GREEN}  Setup Complete!${NC}"
+echo -e "${GREEN}========================================${NC}"
+echo
+echo "Useful commands:"
+echo "  Start bot:      sudo systemctl start pockettts"
+echo "  Stop bot:       sudo systemctl stop pockettts"
+echo "  Restart bot:    sudo systemctl restart pockettts"
+echo "  View status:    sudo systemctl status pockettts"
+echo "  View logs:      journalctl -u pockettts -f"
+echo "  Disable boot:   sudo systemctl disable pockettts"
+echo
+echo "To run the bot manually (without systemd):"
+echo "  cd $SCRIPT_DIR"
+echo "  source venv/bin/activate"
+echo "  python bot.py"
+echo
