whole bunch of crap added fixed or changed. cbf detailing it all you'll figure it out

This commit is contained in:
Jing Kohn 2025-11-06 15:52:46 +10:00
parent 6cd78f1510
commit 8bc16e4d4e
6 changed files with 5129 additions and 418 deletions

27
LOGOASCI.TXT Normal file
View File

@ -0,0 +1,27 @@
██████ ██████ █████ █████ ████ ██████ █████████ ███████ ████████
░░██████ ██████ ███░░░███░░████ ░░██ ███░░░███░█░░░██░░█░░██░░░█░░███░░███
░███░█████░███ ███ ░░███░██░██ ░██ ░███ ░░░ ░ ░██ ░ ░██ █ ░███ ░███
░███░░███ ░███░███ ░███░██ ░██░██ ░░███████ ░██ ░████ ░██████
░███ ░░░ ░███░███ ░███░██ ░████ ░░░░███ ░██ ░██░█ ░███░░███
░███ ░███░░███ ███ ░███ ░███ ███ ░███ ░██ ░██ █ ░███ ░███
█████ █████░░░█████░ ████ ░████░░███████ █████ ███████ ████ ████
░░░░░ ░░░░░ ░░░░░░ ░░░░░ ░░░ ░░░░░░░ ░░░░ ░░░░░░ ░░░░ ░░░░
███████████ ███████ ███████████ ███████ ███████████
░░███░░░░░███ ███░░░░░███░░███░░░░░███ ███░░░░░███ ░█░░░███░░░█
░███ ░███ ███ ░░███░███ ░███ ███ ░░███░ ░███ ░
░██████████ ░███ ░███░██████████ ░███ ░███ ░███
░███░░░░░███░███ ░███░███░░░░░███░███ ░███ ░███
░███ ░███░░███ ███ ░███ ░███░░███ ███ ░███
█████ █████░░░███████░ ███████████ ░░░███████░ █████
░░░░░ ░░░░░ ░░░░░░░ ░░░░░░░░░░░ ░░░░░░░ ░░░░░
█████████ ███████ ███████████ ███████████
███░░░░░███ ███░░░░░███░░███░░░░░░█░█░░░███░░░█
░███ ░░░ ███ ░░███░███ █ ░ ░ ░███ ░
░░█████████ ░███ ░███░███████ ░███
░░░░░░░░███░███ ░███░███░░░█ ░███
███ ░███░░███ ███ ░███ ░ ░███
░░█████████ ░░░███████░ █████ █████
░░░░░░░░░ ░░░░░░░ ░░░░░ ░░░░░

View File

@ -9,11 +9,19 @@ UltraBunt is the **ULTIMATE** Ubuntu setup script that transforms your fresh Ubu
Think of it as a whole bunch of blu-tac'd together bash scripts that:
- 🧙‍♂️ Install up to 560+ essential applications
- 🎪 Organized into 25+ magnificent categories
- 🚀 Handles APT, Snap, Flatpak, and custom installations
- 🚀 Handles `apt`, `snap`, `flatpak`, and `.deb` installers
- 🎨 Makes your terminal look absolutely gorgeous
- 🔒 Set up a native LAMP wordpress site that works without all the ball-ache
- ☕ Saves you pissfarting around in terminal for hours every frikkin time you install it
## ✅ Install Policy
UltraBunt installs apps only via `apt`, `snap`, `.deb`, or `flatpak` on Ubuntu-based systems.
- Python `pip` installations are disabled and have been removed.
- Pip-only packages have been removed from the script and from this README.
- Where possible, equivalents using `apt`, `snap`, `.deb`, or `flatpak` are provided.
## 🎪 THE MAGNIFICENT BUNTAGE CATEGORIES 🎪
### 🔧 Core Utilities - The Foundation of Greatness
@ -50,7 +58,7 @@ Programming languages, frameworks, and development utilities:
**Python3** - Python interpreter [APT]
**Python3-pip** - Python package manager [APT]
**Pipx** - Python app installer [APT]
**Poetry** - Python dependency manager [SCRIPT]
**Poetry** - Python dependency manager [APT]
**Pyenv** - Python version manager [SCRIPT]
**Go** - Go programming language [APT]
**Rust** - Rust programming language [SCRIPT]
@ -80,9 +88,9 @@ Programming languages, frameworks, and development utilities:
**VirtualBox** - Virtualization [SCRIPT]
**QEMU** - Machine emulator [APT]
**Neovim** - Modern Vim editor [APT]
**MkDocs** - Documentation generator [SCRIPT]
**Insomnia** - API testing tool [SCRIPT]
**Zed** - High-performance code editor [SCRIPT]
**MkDocs** - Documentation generator [APT]
**Insomnia** - API testing tool [DEB]
**Zed** - High-performance code editor [DEB]
**Postman** - API development platform [SCRIPT]
**Bruno** - Open-source API client [SCRIPT]
**Bruno (Snap)** - Bruno via Snap [SNAP]
@ -560,9 +568,8 @@ Graphics editing and design applications:
**GIMP (Flatpak)** - GIMP via Flatpak [FLATPAK]
**Inkscape (Snap)** - Inkscape via Snap [SNAP]
**Inkscape (Flatpak)** - Inkscape via Flatpak [FLATPAK]
**Webcamize** - Webcam utility [SCRIPT]
**Durdraw** - ASCII art editor [SCRIPT]
**Pastel** - Color manipulation tool [SCRIPT]
**Webcamize** - Webcam utility [APT]
**Pastel** - Color manipulation tool [APT]
### 📄 Office & Productivity - Get Things Done
Office suites and productivity applications:
@ -585,22 +592,10 @@ Cutting-edge AI and machine learning tools:
**Ollama** - Run LLMs locally [SCRIPT]
**Gollama** - Ollama GUI client [SCRIPT]
**LM Studio** - Local LLM interface [SCRIPT]
**Text Generation WebUI** - Local text generation [SCRIPT]
**Ollama** - Run LLMs locally [SCRIPT]
**Gollama** - Ollama GUI client [SCRIPT]
**LM Studio** - Local LLM interface [SCRIPT]
**Whisper-cpp** - Speech recognition [SCRIPT]
**ComfyUI** - Node-based AI interface [SCRIPT]
**InvokeAI** - Professional AI art [SCRIPT]
**LMDeploy** - LLM deployment toolkit [SCRIPT]
**KoboldCpp** - AI storytelling backend [SCRIPT]
**Automatic1111** - Popular SD interface [SCRIPT]
**Fooocus** - Simplified Stable Diffusion [SCRIPT]
**SD-Next** - Advanced Stable Diffusion [SCRIPT]
**Kohya SS GUI** - LoRA training interface [SCRIPT]
**Faster-Whisper** - Optimized speech recognition [SCRIPT]
**WhisperX** - Enhanced Whisper with alignment [SCRIPT]
**Coqui-STT** - Speech-to-text engine [SCRIPT]
**Piper-TTS** - Text-to-speech synthesis [SCRIPT]
**Mimic3** - Neural text-to-speech [SCRIPT]
**Coqui-TTS** - Advanced text-to-speech [SCRIPT]
**Yai** - AI powered terminal assistant [CUSTOM]
### 🕹️ Gaming Emulators - Retro Gaming

218
instructions-for-claude.txt Normal file
View File

@ -0,0 +1,218 @@
Goal:
Expand an Ubuntu bash installer script so that it configures Cloudflare Firewall rules automatically using the users Zone ID and API Token.
The script should support three security levels — Light, Moderate, and Extreme — all using Cloudflares free-tier Firewall Rules API.
🪟 User Inputs (interactive prompt in terminal)
1. CLOUDFLARE_EMAIL (optional, only for logging)
2. ZONE_ID
3. API_TOKEN
4. DOMAIN_NAME (used for referer-safe rules)
5. SECURITY_LEVEL (choose: light, moderate, or extreme)
🧰 Dependencies (for a clean Ubuntu install)
sudo apt update
sudo apt install -y curl jq
(jq is for parsing JSON responses and checking rule creation success.)
🌩️ Cloudflare API Base Endpoint
https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/firewall/rules
Headers:
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json"
🪄 Security Levels
🟢 LIGHT (basic protection, no admin lockdown)
• Block /xmlrpc.php
• Block /wp-content/ or /wp-includes/ requests not from your domain
Expression:
(http.request.uri.path contains "/xmlrpc.php") or
((http.request.uri.path eq "/wp-content/" or http.request.uri.path eq "/wp-includes/") and not http.referer contains "${DOMAIN_NAME}")
🟡 MODERATE (adds wp-admin/wp-login limits)
Includes Light rules +
Block access to /wp-login.php or /wp-admin/ (except /wp-admin/admin-ajax.php) from outside AU, US, UK.
Expression:
(
http.request.uri.path contains "/wp-login.php" or
(http.request.uri.path contains "/wp-admin/" and http.request.uri.path ne "/wp-admin/admin-ajax.php")
)
and not (ip.geoip.country in {"AU" "US" "UK"})
🔴 EXTREME (maximum free-tier hardening)
Includes Moderate rules +
Block entire site access from sketchy regions (RU, CN, KP, IR, etc.), except known search engine bots (Googlebot, Bingbot).
Expression:
(
ip.geoip.country in {"RU" "CN" "KP" "IR" "VN" "TR" "IN" "NG"}
)
and not cf.client.bot
🧩 Example Bash Logic
Heres the conceptual structure for your installer:
read -p "Enter your Cloudflare Zone ID: " ZONE_ID
read -p "Enter your Cloudflare API Token: " API_TOKEN
read -p "Enter your domain (e.g. example.com): " DOMAIN
read -p "Choose security level (light/moderate/extreme): " LEVEL
API="https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/firewall/rules"
create_rule() {
local desc="$1"
local expr="$2"
echo "Creating rule: $desc..."
curl -s -X POST "$API" \
-H "Authorization: Bearer ${API_TOKEN}" \
-H "Content-Type: application/json" \
--data "[
{
\"description\": \"${desc}\",
\"action\": \"block\",
\"filter\": {\"expression\": \"${expr}\"}
}
]" | jq .
}
if [[ "$LEVEL" == "light" || "$LEVEL" == "moderate" || "$LEVEL" == "extreme" ]]; then
create_rule "Block XMLRPC and unauthorized includes" "(http.request.uri.path contains \"/xmlrpc.php\") or ((http.request.uri.path eq \"/wp-content/\" or http.request.uri.path eq \"/wp-includes/\") and not http.referer contains \"${DOMAIN}\")"
fi
if [[ "$LEVEL" == "moderate" || "$LEVEL" == "extreme" ]]; then
create_rule "Restrict wp-login/wp-admin to AU, US, UK" "((http.request.uri.path contains \"/wp-login.php\" or (http.request.uri.path contains \"/wp-admin/\" and http.request.uri.path ne \"/wp-admin/admin-ajax.php\")) and not (ip.geoip.country in {\"AU\" \"US\" \"UK\"}))"
fi
if [[ "$LEVEL" == "extreme" ]]; then
create_rule "Block access from high-risk countries" "((ip.geoip.country in {\"RU\" \"CN\" \"KP\" \"IR\" \"VN\" \"TR\" \"IN\" \"NG\"}) and not cf.client.bot)"
fi
echo "✅ Cloudflare security rules applied for ${DOMAIN} (${LEVEL} mode)"
extra concept to factor in...
💀 “Mega Bot Block” Expansion for Cloudflare Setup Script
This will:
• Keep Googlebot, Bingbot, DuckDuckGo, Applebot ✅ allowed.
• Block AI scrapers, SEO bots, curl/wget libraries, and other nuisance crawlers.
• Skip blocking /robots.txt so legitimate search engines can still fetch it.
• Use the same ZONE_ID and API_TOKEN you already input earlier.
⚙️ Integration Plan
In your Cloudflare bash installer (from before), add a 4th rule group triggered if user enables “bot blocking.”
At the prompt, include:
read -p "Enable advanced bot blocking? (y/n): " BOTBLOCK
If y, it will add a rule called:
“AI Crawl Control - Block AI & SEO Bots”
💬 Expression (copy-ready for API)
(http.request.uri.path ne "/robots.txt") and (
(http.user_agent contains "SemrushBot") or
(http.user_agent contains "AhrefsBot") or
(http.user_agent contains "Barkrowler") or
(http.user_agent contains "MJ12bot") or
(http.user_agent contains "DotBot") or
(http.user_agent contains "Exabot") or
(http.user_agent contains "Sogou") or
(http.user_agent contains "YandexBot") or
(http.user_agent contains "Baidu") or
(http.user_agent contains "ia_archiver") or
(http.user_agent contains "SemanticaBot") or
(http.user_agent contains "SiteLockSpider") or
(http.user_agent contains "SeznamBot") or
(http.user_agent contains "OpenLinkProfiler") or
(http.user_agent contains "SiteBot") or
(http.user_agent contains "Screaming Frog") or
(http.user_agent contains "DataForSeoBot") or
(http.user_agent contains "SEOkicks") or
(http.user_agent contains "BLEXBot") or
(http.user_agent contains "MegaIndex") or
(http.user_agent contains "MegaIndex.ru") or
(http.user_agent contains "NetcraftSurveyAgent") or
(http.user_agent contains "Apache-HttpClient") or
(http.user_agent contains "Python-urllib") or
(http.user_agent contains "python-requests") or
(http.user_agent contains "libwww-perl") or
(http.user_agent contains "Curl") or
(http.user_agent contains "wget") or
(http.user_agent contains "CensysInspect") or
(http.user_agent contains "ZoominfoBot") or
(http.user_agent contains "MauiBot") or
(http.user_agent contains "spbot") or
(http.user_agent contains "GPTBot") or
(http.user_agent contains "ClaudeBot") or
(http.user_agent contains "Claude-SearchBot") or
(http.user_agent contains "Claude-User") or
(http.user_agent contains "Bytespider") or
(http.user_agent contains "MistralAI-User") or
(http.user_agent contains "Perplexity-User") or
(http.user_agent contains "ProRataInc") or
(http.user_agent contains "Novellum") or
(http.user_agent contains "OAI-SearchBot") or
(http.user_agent contains "Meta-ExternalFetcher") or
(http.user_agent contains "Meta-ExternalAgent")
)
🧠 Add this function into the script
if [[ "$BOTBLOCK" =~ ^[Yy]$ ]]; then
create_rule "AI Crawl Control - Block AI & SEO Bots" \
'(http.request.uri.path ne "/robots.txt") and ((http.user_agent contains "SemrushBot") or (http.user_agent contains "AhrefsBot") or (http.user_agent contains "Barkrowler") or (http.user_agent contains "MJ12bot") or (http.user_agent contains "DotBot") or (http.user_agent contains "Exabot") or (http.user_agent contains "Sogou") or (http.user_agent contains "YandexBot") or (http.user_agent contains "Baidu") or (http.user_agent contains "ia_archiver") or (http.user_agent contains "SemanticaBot") or (http.user_agent contains "SiteLockSpider") or (http.user_agent contains "SeznamBot") or (http.user_agent contains "OpenLinkProfiler") or (http.user_agent contains "SiteBot") or (http.user_agent contains "Screaming Frog") or (http.user_agent contains "DataForSeoBot") or (http.user_agent contains "SEOkicks") or (http.user_agent contains "BLEXBot") or (http.user_agent contains "MegaIndex") or (http.user_agent contains "MegaIndex.ru") or (http.user_agent contains "NetcraftSurveyAgent") or (http.user_agent contains "Apache-HttpClient") or (http.user_agent contains "Python-urllib") or (http.user_agent contains "python-requests") or (http.user_agent contains "libwww-perl") or (http.user_agent contains "Curl") or (http.user_agent contains "wget") or (http.user_agent contains "CensysInspect") or (http.user_agent contains "ZoominfoBot") or (http.user_agent contains "MauiBot") or (http.user_agent contains "spbot") or (http.user_agent contains "GPTBot") or (http.user_agent contains "ClaudeBot") or (http.user_agent contains "Claude-SearchBot") or (http.user_agent contains "Claude-User") or (http.user_agent contains "Bytespider") or (http.user_agent contains "MistralAI-User") or (http.user_agent contains "Perplexity-User") or (http.user_agent contains "ProRataInc") or (http.user_agent contains "Novellum") or (http.user_agent contains "OAI-SearchBot") or (http.user_agent contains "Meta-ExternalFetcher") or (http.user_agent contains "Meta-ExternalAgent"))'
fi
✅ Summary of What This Adds
Rule Type Action Notes
/xmlrpc.php & unauthorized includes Block Basic protection
wp-login & wp-admin by region Block Optional Moderate/Extreme
Country blocks (RU, CN, KP, etc.) Block Optional Extreme
Bot/AI/SEO crawler block Block Optional, keeps search engines allowed

File diff suppressed because it is too large Load Diff

View File

@ -22,16 +22,252 @@ TTS_PITCH="0" # Normal pitch
TTS_VOLUME="10" # Slightly louder
TTS_PUNCTUATION="some" # Read some punctuation for clarity
# Function to speak text using spd-say
# Function to check and install TTS dependencies
install_tts_dependencies() {
echo -e "${CYAN}Checking Text-to-Speech Dependencies...${NC}"
# Check if running with sudo privileges
if [[ "$EUID" -ne 0 ]]; then
echo -e "${RED}Error: This script needs to be run with sudo to install dependencies.${NC}"
echo -e "${YELLOW}Please run: sudo ./ultrabunt-accessible.sh${NC}"
exit 1
fi
local packages_to_install=()
local missing_packages=()
# Check for required packages
echo -e "${YELLOW}Checking required packages...${NC}"
# Speech Dispatcher
if ! dpkg -l | grep -q "^ii.*speech-dispatcher "; then
missing_packages+=("speech-dispatcher")
echo -e " ${RED}${NC} speech-dispatcher (not installed)"
else
echo -e " ${GREEN}${NC} speech-dispatcher (installed)"
fi
# PulseAudio
if ! dpkg -l | grep -q "^ii.*pulseaudio "; then
missing_packages+=("pulseaudio")
echo -e " ${RED}${NC} pulseaudio (not installed)"
else
echo -e " ${GREEN}${NC} pulseaudio (installed)"
fi
# ALSA utilities
if ! dpkg -l | grep -q "^ii.*alsa-utils "; then
missing_packages+=("alsa-utils")
echo -e " ${RED}${NC} alsa-utils (not installed)"
else
echo -e " ${GREEN}${NC} alsa-utils (installed)"
fi
# PulseAudio utilities
if ! dpkg -l | grep -q "^ii.*pulseaudio-utils "; then
missing_packages+=("pulseaudio-utils")
echo -e " ${RED}${NC} pulseaudio-utils (not installed)"
else
echo -e " ${GREEN}${NC} pulseaudio-utils (installed)"
fi
# Festival speech synthesis (fallback TTS engine)
if ! dpkg -l | grep -q "^ii.*festival "; then
missing_packages+=("festival")
echo -e " ${RED}${NC} festival (not installed)"
else
echo -e " ${GREEN}${NC} festival (installed)"
fi
# eSpeak (another TTS engine)
if ! dpkg -l | grep -q "^ii.*espeak "; then
missing_packages+=("espeak")
echo -e " ${RED}${NC} espeak (not installed)"
else
echo -e " ${GREEN}${NC} espeak (installed)"
fi
# If packages are missing, offer to install them
if [[ ${#missing_packages[@]} -gt 0 ]]; then
echo ""
echo -e "${YELLOW}Missing packages detected:${NC}"
for package in "${missing_packages[@]}"; do
echo -e "$package"
done
echo ""
echo -e "${CYAN}These packages are required for text-to-speech functionality.${NC}"
echo -e "${WHITE}Would you like to install them now? (y/n)${NC}"
read -p "Install missing packages? " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
echo -e "${GREEN}Installing missing packages...${NC}"
# Update package list
echo -e "${YELLOW}Updating package list...${NC}"
apt update
# Install missing packages
for package in "${missing_packages[@]}"; do
echo -e "${YELLOW}Installing $package...${NC}"
if apt install -y "$package"; then
echo -e "${GREEN}$package installed successfully${NC}"
else
echo -e "${RED}✗ Failed to install $package${NC}"
fi
done
# Configure audio system
echo -e "${YELLOW}Configuring audio system...${NC}"
# Start PulseAudio if not running
if ! pgrep -x "pulseaudio" > /dev/null && ! pgrep -x "pipewire" > /dev/null; then
echo -e "${YELLOW}Starting PulseAudio...${NC}"
# Get the actual user (not root) if running with sudo
local actual_user="${SUDO_USER:-$USER}"
if [[ -n "$actual_user" && "$actual_user" != "root" ]]; then
sudo -u "$actual_user" pulseaudio --start 2>/dev/null || true
fi
else
echo -e "${GREEN}✓ Audio system is running (PulseAudio/PipeWire)${NC}"
fi
# Configure Speech Dispatcher
echo -e "${YELLOW}Configuring Speech Dispatcher...${NC}"
# Stop Speech Dispatcher service first
systemctl stop speech-dispatcher 2>/dev/null || true
# Create basic Speech Dispatcher config if it doesn't exist
local spd_config_dir="/etc/speech-dispatcher"
if [[ -d "$spd_config_dir" ]]; then
# Ensure Speech Dispatcher can use available TTS engines
if [[ -f "$spd_config_dir/speechd.conf" ]]; then
# Enable espeak as default if available
if command -v espeak >/dev/null 2>&1; then
sed -i 's/^#.*DefaultModule.*espeak/DefaultModule espeak/' "$spd_config_dir/speechd.conf" 2>/dev/null || true
echo -e " ${GREEN}${NC} Set espeak as default TTS engine"
fi
fi
# Create user-specific Speech Dispatcher config
local actual_user="${SUDO_USER:-$USER}"
if [[ -n "$actual_user" && "$actual_user" != "root" ]]; then
local user_spd_dir="/home/$actual_user/.config/speech-dispatcher"
sudo -u "$actual_user" mkdir -p "$user_spd_dir" 2>/dev/null || true
# Create a simple user config that prefers espeak with female voice
if [[ ! -f "$user_spd_dir/speechd.conf" ]]; then
sudo -u "$actual_user" cat > "$user_spd_dir/speechd.conf" << 'EOF'
# User Speech Dispatcher Configuration
LogLevel 3
DefaultModule espeak
DefaultLanguage en
DefaultRate -20
DefaultPitch 0
DefaultVolume 100
DefaultVoiceType female1
EOF
echo -e " ${GREEN}${NC} Created user Speech Dispatcher config with female voice"
fi
# Also create espeak-specific config for female voice
if [[ ! -f "$user_spd_dir/modules/espeak.conf" ]]; then
sudo -u "$actual_user" mkdir -p "$user_spd_dir/modules" 2>/dev/null || true
sudo -u "$actual_user" cat > "$user_spd_dir/modules/espeak.conf" << 'EOF'
# Espeak module configuration
EspeakDefaultVoice "en+f3"
EspeakRate -20
EspeakPitch 0
EspeakVolume 100
EOF
echo -e " ${GREEN}${NC} Created espeak module config with female voice"
fi
fi
fi
# Restart Speech Dispatcher service
echo -e "${YELLOW}Restarting Speech Dispatcher service...${NC}"
systemctl start speech-dispatcher 2>/dev/null || true
sleep 2 # Give it time to start
# Check if Speech Dispatcher is running
if systemctl is-active --quiet speech-dispatcher 2>/dev/null; then
echo -e " ${GREEN}${NC} Speech Dispatcher service is running"
else
echo -e " ${YELLOW}${NC} Speech Dispatcher service may not be running properly"
fi
# Test audio output
echo -e "${YELLOW}Testing audio system...${NC}"
if command -v speaker-test >/dev/null 2>&1; then
echo -e "${CYAN}Running brief audio test (2 seconds)...${NC}"
timeout 2s speaker-test -t sine -f 1000 -l 1 2>/dev/null || echo -e "${YELLOW}Audio test completed (or no audio device available)${NC}"
fi
echo -e "${GREEN}✓ Dependencies installation completed!${NC}"
echo ""
else
echo -e "${YELLOW}Skipping package installation. TTS may not work properly.${NC}"
echo -e "${CYAN}You can install them manually later with:${NC}"
echo -e "${WHITE}sudo apt update && sudo apt install ${missing_packages[*]}${NC}"
echo ""
fi
else
echo -e "${GREEN}✓ All required packages are already installed!${NC}"
fi
# Additional audio system checks
echo -e "${YELLOW}Performing audio system checks...${NC}"
# Check if audio devices are available
if command -v aplay >/dev/null 2>&1; then
local audio_devices=$(aplay -l 2>/dev/null | grep -c "card" || echo "0")
if [[ "$audio_devices" -gt 0 ]]; then
echo -e " ${GREEN}${NC} Audio devices found ($audio_devices)"
else
echo -e " ${YELLOW}${NC} No audio devices detected"
fi
fi
# Check PulseAudio/PipeWire status
if command -v pulseaudio >/dev/null 2>&1 || command -v pipewire >/dev/null 2>&1; then
if pgrep -x "pulseaudio" > /dev/null || pgrep -x "pipewire" > /dev/null; then
echo -e " ${GREEN}${NC} Audio system is running (PulseAudio/PipeWire)"
else
echo -e " ${YELLOW}${NC} Audio system is not running"
fi
fi
# Check if pactl (PulseAudio control) works
if command -v pactl >/dev/null 2>&1; then
if pactl info >/dev/null 2>&1; then
echo -e " ${GREEN}${NC} PulseAudio control interface is working"
else
echo -e " ${YELLOW}${NC} PulseAudio control interface not responding"
fi
fi
echo ""
}
# Function to speak text using spd-say or fallback TTS engines
speak_text() {
local text="$1"
local priority="${2:-text}" # Default priority is 'text'
if [[ "$TTS_ENABLED" == true ]] && command -v spd-say >/dev/null 2>&1; then
if [[ "$TTS_ENABLED" == true ]]; then
# Clean the text of ANSI color codes for speech
local clean_text=$(echo "$text" | sed 's/\x1b\[[0-9;]*m//g')
spd-say \
# Kill any existing TTS processes to prevent overlap
pkill -f "spd-say" 2>/dev/null || true
pkill -f "espeak" 2>/dev/null || true
# Try spd-say first if no fallback is set
if [[ -z "$TTS_FALLBACK" ]] && command -v spd-say >/dev/null 2>&1; then
# Use spd-say with wait flag to prevent overlapping
timeout 10s spd-say \
--voice-type "$TTS_VOICE" \
--rate "$TTS_RATE" \
--pitch "$TTS_PITCH" \
@ -40,6 +276,26 @@ speak_text() {
--priority "$priority" \
--wait \
"$clean_text" 2>/dev/null
# Use fallback TTS engines
elif [[ "$TTS_FALLBACK" == "espeak" ]] && command -v espeak >/dev/null 2>&1; then
# Use espeak directly with similar settings
local espeak_rate=$((TTS_RATE + 175)) # Convert spd-say rate to espeak rate (approx)
# Ensure espeak_rate is within valid range (80-450)
if [[ $espeak_rate -lt 80 ]]; then espeak_rate=80; fi
if [[ $espeak_rate -gt 450 ]]; then espeak_rate=450; fi
timeout 10s espeak \
-s "$espeak_rate" \
-p "$((TTS_PITCH + 50))" \
-a "$((TTS_VOLUME * 20))" \
-v "en+f3" \
"$clean_text" 2>/dev/null
elif [[ "$TTS_FALLBACK" == "festival" ]] && command -v festival >/dev/null 2>&1; then
# Use festival for TTS
timeout 10s echo "$clean_text" | festival --tts 2>/dev/null
fi
fi
}
@ -62,10 +318,77 @@ check_tts_availability() {
echo -e "${WHITE}sudo apt update && sudo apt install speech-dispatcher${NC}"
echo ""
TTS_ENABLED=false
read -p "Press Enter to continue without TTS, or Ctrl+C to exit and install Speech Dispatcher..."
echo -e "${WHITE}Press Enter to continue without TTS, or Ctrl+C to exit and install Speech Dispatcher...${NC}"
read
return 1
fi
echo -e "${YELLOW}Testing Speech Dispatcher functionality...${NC}"
# Test if Speech Dispatcher is actually working with multiple methods
local spd_working=false
# Method 1: Test with spd-say directly
echo -e "${CYAN}Testing spd-say directly...${NC}"
if timeout 5s spd-say -w "Testing speech" 2>/dev/null; then
echo -e "${GREEN}✓ spd-say direct test successful${NC}"
spd_working=true
else
echo -e "${RED}✗ spd-say direct test failed${NC}"
fi
# Method 2: Test with different TTS engines if spd-say failed
if [[ "$spd_working" == false ]]; then
echo -e "${CYAN}Testing alternative TTS engines...${NC}"
# Try espeak directly
if command -v espeak >/dev/null 2>&1; then
echo -e "${YELLOW}Trying espeak directly...${NC}"
if timeout 3s espeak "Testing espeak" 2>/dev/null; then
echo -e "${GREEN}✓ espeak works directly${NC}"
# Update speak_text function to use espeak as fallback
TTS_FALLBACK="espeak"
spd_working=true
else
echo -e "${RED}✗ espeak test failed${NC}"
fi
fi
# Try festival if espeak failed
if [[ "$spd_working" == false ]] && command -v festival >/dev/null 2>&1; then
echo -e "${YELLOW}Trying festival...${NC}"
if timeout 3s echo "Testing festival" | festival --tts 2>/dev/null; then
echo -e "${GREEN}✓ festival works${NC}"
TTS_FALLBACK="festival"
spd_working=true
else
echo -e "${RED}✗ festival test failed${NC}"
fi
fi
fi
# Final result
if [[ "$spd_working" == true ]]; then
echo -e "${GREEN}✓ Text-to-speech is working!${NC}"
TTS_ENABLED=true
if [[ -n "$TTS_FALLBACK" ]]; then
echo -e "${YELLOW}Note: Using $TTS_FALLBACK as fallback TTS engine${NC}"
fi
return 0
else
echo -e "${RED}Warning: Speech Dispatcher found but not working properly!${NC}"
echo -e "${YELLOW}This might be due to audio system issues or configuration problems.${NC}"
echo -e "${CYAN}Troubleshooting steps:${NC}"
echo -e "${WHITE}1. Check if PulseAudio is running: pulseaudio --check${NC}"
echo -e "${WHITE}2. Test audio: speaker-test -c2 -t wav${NC}"
echo -e "${WHITE}3. Restart Speech Dispatcher: sudo systemctl restart speech-dispatcher${NC}"
echo -e "${WHITE}4. Check Speech Dispatcher status: systemctl status speech-dispatcher${NC}"
echo ""
TTS_ENABLED=false
echo -e "${WHITE}Press Enter to continue without TTS...${NC}"
read
return 1
fi
}
# Function to test TTS and let user adjust settings
@ -78,6 +401,9 @@ test_and_configure_tts() {
announce "Testing your text-to-speech settings..." "$YELLOW"
speak_text "This is a test of the text to speech system. Can you hear this clearly?"
# Give time for speech to complete
sleep 2
echo ""
echo -e "${WHITE}TTS Settings Test Complete${NC}"
echo -e "${CYAN}Current settings:${NC}"
@ -109,26 +435,39 @@ test_and_configure_tts() {
2)
TTS_RATE="-40"
announce "Voice speed set to slower. Testing..." "$CYAN"
# Update Speech Dispatcher config if needed
update_spd_config
speak_text "This is the new slower speed setting."
sleep 3
;;
3)
TTS_RATE="0"
announce "Voice speed set to normal. Testing..." "$CYAN"
# Update Speech Dispatcher config if needed
update_spd_config
speak_text "This is the normal speed setting."
sleep 3
;;
4)
TTS_VOLUME="30"
announce "Voice volume set to louder. Testing..." "$CYAN"
# Update Speech Dispatcher config if needed
update_spd_config
speak_text "This is the louder volume setting."
sleep 3
;;
5)
TTS_VOLUME="0"
announce "Voice volume set to normal. Testing..." "$CYAN"
# Update Speech Dispatcher config if needed
update_spd_config
speak_text "This is the normal volume setting."
sleep 3
;;
6)
announce "Testing current settings..." "$YELLOW"
speak_text "This is a test of your current text to speech settings. How does this sound?"
sleep 2
;;
7)
TTS_ENABLED=false
@ -143,6 +482,33 @@ test_and_configure_tts() {
fi
}
# Function to update Speech Dispatcher configuration with current settings
update_spd_config() {
# Only update if we have a user config directory
local actual_user="${SUDO_USER:-$USER}"
if [[ -n "$actual_user" && "$actual_user" != "root" ]]; then
local user_spd_dir="/home/$actual_user/.config/speech-dispatcher"
# Update the main config file if it exists
if [[ -f "$user_spd_dir/speechd.conf" ]]; then
# Update rate setting
sed -i "s/^DefaultRate.*/DefaultRate $TTS_RATE/" "$user_spd_dir/speechd.conf" 2>/dev/null || true
# Update volume setting
sed -i "s/^DefaultVolume.*/DefaultVolume $TTS_VOLUME/" "$user_spd_dir/speechd.conf" 2>/dev/null || true
fi
# Update espeak module config if it exists
if [[ -f "$user_spd_dir/modules/espeak.conf" ]]; then
sed -i "s/^EspeakRate.*/EspeakRate $TTS_RATE/" "$user_spd_dir/modules/espeak.conf" 2>/dev/null || true
sed -i "s/^EspeakVolume.*/EspeakVolume $TTS_VOLUME/" "$user_spd_dir/modules/espeak.conf" 2>/dev/null || true
fi
# Restart Speech Dispatcher to apply changes
systemctl restart speech-dispatcher 2>/dev/null || true
sleep 1
fi
}
# Function to provide audio navigation help
provide_navigation_help() {
announce "Navigation Help for Ultrabunt Installer" "$CYAN" "important"
@ -184,6 +550,14 @@ main() {
exit 1
fi
# Install TTS dependencies if needed (requires sudo)
if [[ "$EUID" -eq 0 ]]; then
install_tts_dependencies
else
echo -e "${YELLOW}Note: Running without sudo. If TTS doesn't work, try: sudo ./ultrabunt-accessible.sh${NC}"
echo ""
fi
# Check TTS availability
check_tts_availability

File diff suppressed because it is too large Load Diff