KI-Chat-Bot-Eugen/gui.py
Claude d3f2fa43c3
Fix bare except clauses for better error handling
Replace 5 bare except clauses with 'except Exception:' to improve
error handling and prevent catching system exits and keyboard interrupts:

- gui.py:155 - Queue event processing
- setup_wizard.py:184 - API response parsing
- test_credentials.py:213 - Response JSON parsing
- test_credentials.py:240 - Error response parsing
- test_credentials.py:257 - Response text formatting

This change improves code quality and follows Python best practices
for exception handling.
2026-01-10 11:08:28 +00:00

327 lines
11 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
Dashboard GUI for Eugen Bot
Live monitoring interface using FreeSimpleGUI
"""
import FreeSimpleGUI as sg
import threading
from datetime import datetime
from queue import Queue
class Dashboard:
"""Live monitoring dashboard for bot activity"""
def __init__(self, bot=None):
"""
Initialize dashboard
Args:
bot: Reference to the main bot instance
"""
self.bot = bot
sg.theme('DarkBlue3')
# Event queue for thread-safe updates
self.event_queue = Queue()
self.window = None
self.is_running = False
# Statistics
self.stats = {
"messages": 0,
"api_calls": 0,
"errors": 0,
"start_time": datetime.now()
}
def log_event(self, event_type, data):
"""
Add event to queue for display
Args:
event_type (str): Type of event (chat_message, api_call, etc.)
data (dict): Event data
"""
timestamp = datetime.now().strftime("%H:%M:%S")
if event_type == "chat_message":
msg = f"{timestamp} | {data['username']}: {data['content']}"
self.stats["messages"] += 1
elif event_type == "mention_detected":
msg = f"{timestamp} | [MENTION] Bot addressed by {data['username']}"
elif event_type == "api_call":
msg = f"{timestamp} | [API] → Perplexity ({data.get('model', 'sonar-pro')})"
self.stats["api_calls"] += 1
elif event_type == "api_response":
preview = data['content'][:60] + "..." if len(data['content']) > 60 else data['content']
msg = f"{timestamp} | [RESPONSE] {preview}"
elif event_type == "bot_response":
preview = data['content'][:60] + "..." if len(data['content']) > 60 else data['content']
msg = f"{timestamp} | Eugen: @{data['username']} {preview}"
elif event_type == "error":
msg = f"{timestamp} | ❌ ERROR: {data['error']}"
self.stats["errors"] += 1
elif event_type == "info":
msg = f"{timestamp} | {data['message']}"
elif event_type == "warning":
msg = f"{timestamp} | ⚠ {data['message']}"
elif event_type == "context_loaded":
msg = f"{timestamp} | [CONTEXT] Loaded {data['count']} messages for {data['username']}"
else:
msg = f"{timestamp} | {event_type}: {data}"
self.event_queue.put(msg)
def create_layout(self):
"""Create the GUI layout"""
# Header
header = [
[sg.Text("EUGEN BOT - LIVE DASHBOARD", font=("Arial", 16, "bold"))],
[sg.Text("Status: 🟢 RUNNING", key="-STATUS-", font=("Arial", 10))],
[sg.Text("Uptime: 00:00:00", key="-UPTIME-", size=(20, 1)),
sg.Text("Messages: 0", key="-MSG-COUNT-", size=(20, 1)),
sg.Text("API Calls: 0", key="-API-COUNT-", size=(20, 1)),
sg.Text("Errors: 0", key="-ERROR-COUNT-", size=(20, 1))],
[sg.HorizontalSeparator()]
]
# Live feed
feed = [
[sg.Text("LIVE ACTIVITY FEED", font=("Arial", 12, "bold"))],
[sg.Multiline(
size=(140, 25),
key="-LOG-",
disabled=True,
autoscroll=True,
font=("Courier New", 9)
)]
]
# Control buttons
controls = [
[sg.HorizontalSeparator()],
[
sg.Button("Clear Log", key="-CLEAR-"),
sg.Button("Reset Stats", key="-RESET-"),
sg.Button("Stop Bot", key="-STOP-", button_color=("white", "red"))
]
]
# Combine all sections
layout = header + feed + controls
return layout
def run(self):
"""Run the dashboard GUI in main thread"""
layout = self.create_layout()
self.window = sg.Window(
"Eugen Bot Dashboard",
layout,
finalize=True,
size=(1000, 650)
)
self.is_running = True
# Main event loop
while self.is_running:
event, values = self.window.read(timeout=100)
# Handle window close
if event == sg.WINDOW_CLOSED or event == "-STOP-":
self.is_running = False
if self.bot:
self.bot.stop()
break
# Handle clear log
if event == "-CLEAR-":
self.window["-LOG-"].update("")
# Handle reset stats
if event == "-RESET-":
self.stats = {
"messages": 0,
"api_calls": 0,
"errors": 0,
"start_time": datetime.now()
}
# Update log with queued events
while not self.event_queue.empty():
try:
msg = self.event_queue.get_nowait()
self.window["-LOG-"].print(msg)
except Exception:
break
# Update statistics
self._update_stats()
self.window.close()
def _update_stats(self):
"""Update statistics display"""
if not self.window:
return
# Calculate uptime
uptime = datetime.now() - self.stats["start_time"]
hours, remainder = divmod(int(uptime.total_seconds()), 3600)
minutes, seconds = divmod(remainder, 60)
uptime_str = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
# Update displays
self.window["-UPTIME-"].update(f"Uptime: {uptime_str}")
self.window["-MSG-COUNT-"].update(f"Messages: {self.stats['messages']}")
self.window["-API-COUNT-"].update(f"API Calls: {self.stats['api_calls']}")
self.window["-ERROR-COUNT-"].update(f"Errors: {self.stats['errors']}")
def show_error(self, title, message):
"""Show error popup"""
sg.popup_error(message, title=title)
def show_info(self, title, message):
"""Show info popup"""
sg.popup(message, title=title)
def stop(self):
"""Stop the dashboard"""
self.is_running = False
if self.window:
self.window.close()
class SetupWizard:
"""Configuration wizard for first-time setup"""
def __init__(self):
sg.theme('DarkBlue3')
def run(self):
"""
Run the setup wizard
Returns:
dict: Configuration values or None if cancelled
"""
layout = [
[sg.Text("EUGEN CONFIGURATION WIZARD", font=("Arial", 16, "bold"))],
[sg.HorizontalSeparator()],
[sg.Text("TWITCH CONFIGURATION", font=("Arial", 12, "bold"))],
[sg.Text("Bot Nickname:", size=(20, 1)), sg.Input("Eugen", key="-BOT-NAME-")],
[sg.Text("OAuth Token:", size=(20, 1)), sg.Input("oauth:", key="-OAUTH-", password_char="*")],
[sg.Text("Channel:", size=(20, 1)), sg.Input("#", key="-CHANNEL-")],
[sg.HorizontalSeparator()],
[sg.Text("PERPLEXITY CONFIGURATION", font=("Arial", 12, "bold"))],
[sg.Text("API Key:", size=(20, 1)), sg.Input("pplx-", key="-API-KEY-", password_char="*")],
[sg.Text("Model:", size=(20, 1)),
sg.Combo([
"sonar-pro",
"sonar",
"sonar-reasoning",
"sonar-reasoning-pro",
"sonar-deep-research"
], default_value="sonar-pro", key="-MODEL-", size=(25, 1)),
sg.Button("?", key="-MODEL-INFO-", size=(2, 1))],
[sg.Text("", size=(20, 1)),
sg.Text("Recommended: sonar-pro (chat bots)", font=("Arial", 8), text_color="gray")],
[sg.Text("Max Tokens:", size=(20, 1)), sg.Input("450", key="-TOKENS-")],
[sg.HorizontalSeparator()],
[sg.Checkbox("Enable Debug Mode", default=True, key="-DEBUG-")],
[sg.Checkbox("Auto Reconnect", default=True, key="-RECONNECT-")],
[sg.HorizontalSeparator()],
[sg.Button("Save & Start", key="-SAVE-"), sg.Button("Cancel", key="-CANCEL-")]
]
window = sg.Window("Eugen Setup", layout)
config = None
while True:
event, values = window.read()
if event == sg.WINDOW_CLOSED or event == "-CANCEL-":
break
# Show model info
if event == "-MODEL-INFO-":
model_info = """PERPLEXITY API MODELS (2026):
🔵 sonar-pro (RECOMMENDED FOR CHAT BOTS)
- Deeper content understanding
- 2x more search results than sonar
- Enhanced search accuracy
- Best for complex, multi-step queries
- Built on Llama 3.3 70B
➜ Use this for chat bots!
🟢 sonar
- Lightweight and fast
- Lower cost
- Simple question-answer features
- Good for speed-optimized applications
- Built on Llama 3.3 70B
🧠 sonar-reasoning
- Real-time reasoning with search
- Shows reasoning process
- Good for problem-solving
- Moderate speed
⚡ sonar-reasoning-pro
- Powered by DeepSeek-R1
- Advanced reasoning capabilities
- Visible reasoning content via API
- Best for complex logical tasks
- Higher cost
📊 sonar-deep-research
- Long-form research reports
- Source-dense output
- Best for detailed analysis
- Slower, comprehensive responses
RECOMMENDATION:
• Chat Bots: sonar-pro
• Quick answers: sonar
• Complex reasoning: sonar-reasoning-pro
• Research: sonar-deep-research"""
sg.popup_scrolled(model_info, title="Model Information", size=(70, 30))
continue
if event == "-SAVE-":
# Validate inputs
if not values["-OAUTH-"].startswith("oauth:"):
sg.popup_error("Twitch OAuth token must start with 'oauth:'")
continue
if not values["-CHANNEL-"].startswith("#"):
sg.popup_error("Channel must start with '#'")
continue
if not values["-API-KEY-"].startswith("pplx-"):
sg.popup_error("Perplexity API key must start with 'pplx-'")
continue
# Build config
config = {
"TWITCH_BOT_NICKNAME": values["-BOT-NAME-"],
"TWITCH_OAUTH_TOKEN": values["-OAUTH-"],
"TWITCH_CHANNEL": values["-CHANNEL-"],
"PERPLEXITY_API_KEY": values["-API-KEY-"],
"PERPLEXITY_MODEL": values["-MODEL-"],
"MAX_TOKENS": values["-TOKENS-"],
"DEBUG_MODE": "true" if values["-DEBUG-"] else "false",
"AUTO_RECONNECT": "true" if values["-RECONNECT-"] else "false"
}
break
window.close()
return config