Merge pull request #3 from Kenearos/claude/setup-ai-chat-wizard-wNFh2

Setup wizard for AI chat integration
This commit is contained in:
Kenearos 2026-01-02 21:15:34 +01:00 committed by GitHub
commit 49d90df3cb
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 409 additions and 15 deletions

View file

@ -42,11 +42,17 @@ pip install -r requirements.txt
### Configuration ### Configuration
#### Option 1: Setup Wizard (Recommended) #### Option 1: Setup Wizard (Recommended)
Simply run the bot and the setup wizard will guide you: Run the interactive setup wizard to configure the bot:
```bash ```bash
python chatbot.py python setup_wizard.py
``` ```
The wizard will:
- Guide you through getting Twitch OAuth token
- Help you set up Perplexity API key
- Validate your credentials
- Create necessary directories and config files
#### Option 2: Manual Configuration #### Option 2: Manual Configuration
Copy `.env.example` to `.env` and fill in your credentials: Copy `.env.example` to `.env` and fill in your credentials:
```bash ```bash

View file

@ -79,18 +79,25 @@ class Config:
def get_system_prompt(self): def get_system_prompt(self):
"""Returns the system prompt for the AI""" """Returns the system prompt for the AI"""
return """Du bist Eugen, ein hilfreicher und freundlicher Twitch-Chat-Bot. return """Du bist Kene's AI-Assistent, der für ihn im Chat antwortet.
Du bist Experte für folgende Themen: WICHTIG: Du antwortest im Namen von Kene, aber als sein Helfer. Sprich in der ersten Person für ihn ("Ich...", "Mein Setup..."), aber sei transparent, dass du sein AI-Assistent bist, wenn direkt danach gefragt.
- Gaming: World of Warcraft, Elden Ring, Gamedev
- 3D-Druck: Prusa i3, Bambu Labs, Creality
- Tech: Python, Linux, Home Automation
Verhalte dich wie ein echter Chat-Teilnehmer: Über Kene:
- Sei freundlich und hilfsbereit - Streamer, Botter (Automatisierung/Coding), Gamer
- Antworte kurz und prägnant (max 2-3 Sätze für Twitch-Chat) - 3D-Druck mit Bambu X1C und H2C
- Verwende gelegentlich Gaming- oder Tech-Slang - Themen: Gaming (WoW, Elden Ring, Gamedev), 3D-Druck, Coding/Bots, Linux, Home Automation
- Beziehe dich auf vorherige Gespräche wenn möglich - Humor: Vielseitig - Sarkasmus, Dad-Jokes, Gaming-Memes, Spaß & Fun
- Sei humorvoll aber respektvoll - Chat-Stil: Locker und direkt, aber technisch detailliert wenn nötig
Wenn du etwas nicht weißt, sage es ehrlich. Wenn die Frage nicht zu deinen Themen passt, biete trotzdem Hilfe an oder verweise auf passende Ressourcen.""" Politische Haltung:
- Linkspolitisch eingestellt
- Argumentierst klar gegen rechte Positionen, Rechtsmitte und Nazis
- Bei politischen Themen: Klare Kante, aber sachlich bleiben
Chat-Verhalten:
- Antworte kurz (2-3 Sätze max für Twitch-Chat)
- Authentisch und natürlich, wie Kene selbst sprechen würde
- Bei Tech/3D-Druck-Fragen: Gerne detaillierter mit konkreten Tipps
- Beziehe dich auf frühere Chat-Nachrichten wenn möglich
- Ehrlich sagen wenn du etwas nicht weißt"""

View file

@ -1,5 +1,5 @@
irc==20.1.0 irc==20.1.0
python-dotenv==1.0.0 python-dotenv==1.0.0
PySimpleGUI==4.60.0 PySimpleGUI==5.0.8.3
requests==2.31.0 requests==2.31.0
httpx==0.25.0 httpx==0.25.0

381
setup_wizard.py Normal file
View file

@ -0,0 +1,381 @@
"""
Setup Wizard for Eugen Twitch Bot
Interactive configuration tool for first-time setup
"""
import os
import sys
import asyncio
import socket
import getpass
from pathlib import Path
from dotenv import set_key, load_dotenv
import httpx
class Colors:
"""ANSI color codes for terminal output"""
HEADER = '\033[95m'
OKBLUE = '\033[94m'
OKCYAN = '\033[96m'
OKGREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
def print_header(text):
"""Print colored header"""
print(f"\n{Colors.HEADER}{Colors.BOLD}{'='*60}{Colors.ENDC}")
print(f"{Colors.HEADER}{Colors.BOLD}{text.center(60)}{Colors.ENDC}")
print(f"{Colors.HEADER}{Colors.BOLD}{'='*60}{Colors.ENDC}\n")
def print_success(text):
"""Print success message"""
print(f"{Colors.OKGREEN}{text}{Colors.ENDC}")
def print_error(text):
"""Print error message"""
print(f"{Colors.FAIL}{text}{Colors.ENDC}")
def print_info(text):
"""Print info message"""
print(f"{Colors.OKCYAN} {text}{Colors.ENDC}")
def print_warning(text):
"""Print warning message"""
print(f"{Colors.WARNING}{text}{Colors.ENDC}")
async def validate_twitch_token(token, bot_nickname):
"""
Validate Twitch OAuth token by attempting IRC connection
Args:
token (str): OAuth token
bot_nickname (str): Bot nickname for authentication
Returns:
bool: True if valid
"""
if not token.startswith("oauth:"):
print_error("Token muss mit 'oauth:' beginnen!")
return False
try:
print_info("Validiere Twitch-Verbindung...")
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
sock.settimeout(5)
sock.connect(('irc.chat.twitch.tv', 6667))
# Send authentication
sock.send(f"PASS {token}\r\n".encode())
sock.send(f"NICK {bot_nickname}\r\n".encode())
response = sock.recv(1024).decode()
if "Login authentication failed" in response:
print_error("Twitch OAuth Token ist ungültig!")
return False
print_success("Twitch-Verbindung erfolgreich!")
return True
except Exception as e:
print_warning(f"Konnte Twitch-Verbindung nicht testen: {e}")
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
return True
async def validate_perplexity_key(api_key, model="sonar-pro"):
"""
Validate Perplexity API key with test request
Note: Validation uses the specified model (default: sonar-pro).
If your API key doesn't have access to this model, validation may fail
even with a valid key for other models.
Args:
api_key (str): Perplexity API key
model (str): Model to test with (defaults to sonar-pro)
Returns:
tuple: (bool success, bool should_retry) - success indicates if validation passed,
should_retry indicates if user should be prompted to retry
"""
try:
print_info(f"Validiere Perplexity API-Key mit Modell '{model}'...")
async with httpx.AsyncClient(timeout=10.0) as client:
response = await client.post(
"https://api.perplexity.ai/chat/completions",
json={
"model": model,
"messages": [{"role": "user", "content": "test"}],
"max_tokens": 10
},
headers={
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
)
if response.status_code == 200:
print_success("Perplexity API-Key ist gültig!")
return (True, False)
elif response.status_code == 401:
print_error("Perplexity API-Key ist ungültig!")
return (False, True)
else:
print_warning(f"Unerwartete Antwort: {response.status_code}")
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
return (True, False)
except Exception as e:
print_warning(f"Konnte Perplexity API nicht testen: {e}")
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
return (True, False)
def create_env_file(config):
"""
Create or update .env file with configuration
Args:
config (dict): Configuration dictionary
"""
env_file = ".env"
# Create .env if it doesn't exist
if not os.path.exists(env_file):
Path(env_file).touch()
# Write all config values
for key, value in config.items():
set_key(env_file, key, value)
print_success(f".env Datei erstellt/aktualisiert!")
def create_directories():
"""Create necessary directories for bot operation"""
directories = [
"data",
"data/conversations",
"logs"
]
for directory in directories:
Path(directory).mkdir(parents=True, exist_ok=True)
print_success("Verzeichnisse erstellt!")
def get_input(prompt, default=None, required=True, secret=False):
"""
Get user input with validation
Args:
prompt (str): Input prompt
default (str): Default value
required (bool): Whether input is required
secret (bool): Whether to hide input (for passwords)
Returns:
str: User input
"""
if default:
prompt_text = f"{prompt} [{default}]: "
else:
prompt_text = f"{prompt}: "
while True:
if secret:
value = getpass.getpass(prompt_text)
else:
value = input(prompt_text)
# Use default if provided and input is empty
if not value and default:
return default
# Check if required
if required and not value:
print_error("Dieses Feld ist erforderlich!")
continue
return value
async def run_wizard():
"""Main wizard flow"""
# Welcome
print_header("🤖 EUGEN BOT SETUP WIZARD 🤖")
print("Willkommen beim Setup-Assistenten für deinen Twitch-Bot!")
print("Dieser Wizard führt dich durch die Erstkonfiguration.\n")
print_info("Du benötigst:")
print(" 1. Einen Twitch OAuth Token")
print(" 2. Deinen Twitch Channel-Namen")
print(" 3. Einen Perplexity API Key")
print()
input("Drücke ENTER um zu starten...")
# Configuration dictionary
config = {}
# Step 1: Twitch Configuration
print_header("SCHRITT 1: TWITCH KONFIGURATION")
print_info("Twitch OAuth Token generieren:")
print(" → Gehe zu: https://twitchtokengenerator.com")
print(" → Wähle 'Bot Chat Token'")
print(" → Authorisiere und kopiere das 'oauth:...' Token")
print()
while True:
token = get_input("Twitch OAuth Token", secret=True, required=True)
if not token.startswith("oauth:"):
print_warning("Token sollte mit 'oauth:' beginnen. Füge ich hinzu...")
token = f"oauth:{token}"
config['TWITCH_OAUTH_TOKEN'] = token
break
config['TWITCH_CHANNEL'] = get_input(
"Twitch Channel Name (ohne #)",
default="keneraosmd",
required=True
)
# Add # if not present
if not config['TWITCH_CHANNEL'].startswith('#'):
config['TWITCH_CHANNEL'] = f"#{config['TWITCH_CHANNEL']}"
config['TWITCH_BOT_NICKNAME'] = get_input(
"Bot Nickname",
default="Eugen",
required=True
)
# Validate Twitch
if not await validate_twitch_token(config['TWITCH_OAUTH_TOKEN'], config['TWITCH_BOT_NICKNAME']):
retry = input("\nTrotzdem fortfahren? (j/n): ")
if retry.lower() != 'j':
print_error("Setup abgebrochen!")
return False
# Step 2: Perplexity Configuration
print_header("SCHRITT 2: PERPLEXITY API")
print_info("Perplexity API Key erhalten:")
print(" → Gehe zu: https://www.perplexity.ai/settings/api")
print(" → Erstelle einen neuen API Key")
print(" → Kopiere den Key (beginnt mit 'pplx-...')")
print()
while True:
api_key = get_input("Perplexity API Key", secret=True, required=True)
config['PERPLEXITY_API_KEY'] = api_key
success, should_retry = await validate_perplexity_key(api_key)
if success:
break
if should_retry:
retry = input("\nErneut versuchen? (j/n): ")
if retry.lower() != 'j':
print_error("Setup abgebrochen!")
return False
# Step 3: Advanced Settings
print_header("SCHRITT 3: ERWEITERTE EINSTELLUNGEN")
print("Möchtest du erweiterte Einstellungen konfigurieren?")
advanced = input("(j/n, default: n): ").lower() == 'j'
if advanced:
config['PERPLEXITY_MODEL'] = get_input(
"Perplexity Modell",
default="sonar-pro"
)
config['MAX_TOKENS'] = get_input(
"Max Tokens pro Antwort",
default="450"
)
config['DEBUG_MODE'] = get_input(
"Debug Mode aktivieren?",
default="false"
)
config['CONTEXT_RETENTION_HOURS'] = get_input(
"Context Retention (Stunden)",
default="1"
)
else:
config['PERPLEXITY_MODEL'] = "sonar-pro"
config['MAX_TOKENS'] = "450"
config['DEBUG_MODE'] = "false"
config['CONTEXT_RETENTION_HOURS'] = "1"
# Step 4: Create files and directories
print_header("SCHRITT 4: SETUP ABSCHLIESSEN")
print_info("Erstelle Konfigurationsdateien...")
create_env_file(config)
create_directories()
# Final summary
print_header("✅ SETUP ERFOLGREICH!")
print(f"{Colors.OKGREEN}Deine Konfiguration:{Colors.ENDC}")
print(f" Channel: {config['TWITCH_CHANNEL']}")
print(f" Bot Name: {config['TWITCH_BOT_NICKNAME']}")
print(f" Modell: {config['PERPLEXITY_MODEL']}")
print(f" Max Tokens: {config['MAX_TOKENS']}")
print()
print_info("Nächste Schritte:")
print(" 1. Starte den Bot mit: python chatbot.py")
print(" 2. Der Bot verbindet sich mit Twitch")
print(" 3. Erwähne den Bot im Chat mit '@Eugen' oder 'Eugen:'")
print()
print_success("Viel Spaß mit deinem Bot! 🚀")
return True
def main():
"""Main entry point"""
try:
# Check if already configured
if os.path.exists('.env'):
load_dotenv()
if os.getenv('TWITCH_OAUTH_TOKEN') and os.getenv('PERPLEXITY_API_KEY'):
print_warning(".env Datei existiert bereits!")
reconfigure = input("Möchtest du die Konfiguration überschreiben? (j/n): ")
if reconfigure.lower() != 'j':
print_info("Setup abgebrochen. Nutze die bestehende Konfiguration.")
return
# Run async wizard
success = asyncio.run(run_wizard())
if not success:
sys.exit(1)
except KeyboardInterrupt:
print()
print_warning("Setup abgebrochen!")
sys.exit(1)
except Exception as e:
print_error(f"Fehler während des Setups: {e}")
sys.exit(1)
if __name__ == "__main__":
main()