fix: replace emoji characters with ASCII-safe markers for Windows compatibility
- Replace Unicode emoji (✓, ⚠️) with [OK] and [WARN] in audio_preprocessor.py
to prevent UnicodeEncodeError on Windows console (cp1252 codec)
- Add auto-update dependencies function to bot.py for easier maintenance
- Remove setup_linux.sh (no longer needed)
- Update .gitignore to exclude VS Code launch.json
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -124,4 +124,5 @@ venv.bak/
|
|||||||
.numba_cache/
|
.numba_cache/
|
||||||
# Gemini files
|
# Gemini files
|
||||||
GEMINI.md
|
GEMINI.md
|
||||||
PROGRESS.md
|
PROGRESS.md
|
||||||
|
.vscode/launch.json
|
||||||
|
|||||||
@@ -190,16 +190,16 @@ def print_audio_analysis(file_path: str) -> None:
|
|||||||
print(f"\n{'=' * 50}")
|
print(f"\n{'=' * 50}")
|
||||||
print(f"Audio Analysis: {info['path']}")
|
print(f"Audio Analysis: {info['path']}")
|
||||||
print(f"{'=' * 50}")
|
print(f"{'=' * 50}")
|
||||||
print(f" Sample Rate: {info['sample_rate']} Hz {'⚠️ (should be 22050)' if info['needs_resampling'] else '✓'}")
|
print(f" Sample Rate: {info['sample_rate']} Hz {'[WARN] (should be 22050)' if info['needs_resampling'] else '[OK]'}")
|
||||||
print(f" Duration: {info['duration_seconds']:.2f}s", end="")
|
print(f" Duration: {info['duration_seconds']:.2f}s", end="")
|
||||||
if info['is_too_short']:
|
if info['is_too_short']:
|
||||||
print(" ⚠️ (too short, aim for 5-15s)")
|
print(" [WARN] (too short, aim for 5-15s)")
|
||||||
elif info['is_too_long']:
|
elif info['is_too_long']:
|
||||||
print(" ⚠️ (quite long, 5-15s is ideal)")
|
print(" [WARN] (quite long, 5-15s is ideal)")
|
||||||
else:
|
else:
|
||||||
print(" ✓")
|
print(" [OK]")
|
||||||
print(f" Channels: {'Stereo' if info['is_stereo'] else 'Mono'} {'⚠️ (will convert to mono)' if info['is_stereo'] else '✓'}")
|
print(f" Channels: {'Stereo' if info['is_stereo'] else 'Mono'} {'[WARN] (will convert to mono)' if info['is_stereo'] else '[OK]'}")
|
||||||
print(f" Max Amplitude: {info['max_amplitude']:.3f} {'✓' if info['is_normalized'] else '⚠️ (low volume)'}")
|
print(f" Max Amplitude: {info['max_amplitude']:.3f} {'[OK]' if info['is_normalized'] else '[WARN] (low volume)'}")
|
||||||
print(f" RMS Level: {info['rms_level']:.4f}")
|
print(f" RMS Level: {info['rms_level']:.4f}")
|
||||||
print(f" Noise Floor: {info['estimated_noise_floor']:.4f}")
|
print(f" Noise Floor: {info['estimated_noise_floor']:.4f}")
|
||||||
print(f"{'=' * 50}\n")
|
print(f"{'=' * 50}\n")
|
||||||
|
|||||||
22
bot.py
22
bot.py
@@ -1,6 +1,8 @@
|
|||||||
import numba_config
|
import numba_config
|
||||||
import asyncio
|
import asyncio
|
||||||
import io
|
import io
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -365,7 +367,27 @@ class TTSBot(commands.Bot):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def auto_update_dependencies() -> None:
|
||||||
|
"""Auto-update pip packages on startup."""
|
||||||
|
try:
|
||||||
|
print("Checking for package updates...")
|
||||||
|
result = subprocess.run(
|
||||||
|
[sys.executable, "-m", "pip", "install", "-r", "requirements.txt", "-U", "-q"],
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=False
|
||||||
|
)
|
||||||
|
if result.returncode == 0:
|
||||||
|
print("Packages updated successfully (or already up to date)")
|
||||||
|
else:
|
||||||
|
print(f"Warning: Package update had issues: {result.stderr}")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Warning: Could not auto-update packages: {e}")
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
|
auto_update_dependencies()
|
||||||
|
|
||||||
errors = Config.validate()
|
errors = Config.validate()
|
||||||
if errors:
|
if errors:
|
||||||
print("Configuration errors:")
|
print("Configuration errors:")
|
||||||
|
|||||||
213
setup_linux.sh
213
setup_linux.sh
@@ -1,213 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# Vox 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} Vox 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/vox.service"
|
|
||||||
|
|
||||||
cat > "$SERVICE_FILE" << EOF
|
|
||||||
[Unit]
|
|
||||||
Description=Vox 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=vox
|
|
||||||
|
|
||||||
# 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/vox.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 vox
|
|
||||||
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 vox
|
|
||||||
echo -e " ${GREEN}✓${NC} Service started"
|
|
||||||
sleep 2
|
|
||||||
echo
|
|
||||||
echo " Service status:"
|
|
||||||
sudo systemctl status vox --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 vox"
|
|
||||||
echo " Stop bot: sudo systemctl stop vox"
|
|
||||||
echo " Restart bot: sudo systemctl restart vox"
|
|
||||||
echo " View status: sudo systemctl status vox"
|
|
||||||
echo " View logs: journalctl -u vox -f"
|
|
||||||
echo " Disable boot: sudo systemctl disable vox"
|
|
||||||
echo
|
|
||||||
echo "To run the bot manually (without systemd):"
|
|
||||||
echo " cd $SCRIPT_DIR"
|
|
||||||
echo " source venv/bin/activate"
|
|
||||||
echo " python bot.py"
|
|
||||||
echo
|
|
||||||
Reference in New Issue
Block a user