Add comprehensive credential validation and troubleshooting tools
This commit adds robust diagnostic tools to help users identify and fix authentication issues with Twitch OAuth and Perplexity API. New Features: - test_credentials.py: Comprehensive credential validator with detailed diagnostics - Tests Twitch OAuth token with IRC authentication - Validates Perplexity API key and model access - Provides specific error messages and actionable fixes - Automatically tests fallback models (sonar-pro → sonar) - TROUBLESHOOTING.md: Complete troubleshooting guide - Common error messages and solutions - Step-by-step diagnostic procedures - Quick reference for file locations and commands Improvements to setup_wizard.py: - Enhanced Twitch token validation with detailed error messages - Added Perplexity model fallback (sonar-pro → sonar) - Better error handling with specific solutions - Recommends working model if primary model unavailable Documentation Updates: - README.md: Added credential testing section with examples - CLAUDE.md: Updated with new tools and testing procedures - Comprehensive troubleshooting section in README This addresses the common authentication failures users encounter during initial setup and provides clear paths to resolution.
This commit is contained in:
parent
f45f73e335
commit
ddedd4867c
5 changed files with 807 additions and 53 deletions
24
CLAUDE.md
24
CLAUDE.md
|
|
@ -28,6 +28,8 @@
|
|||
```
|
||||
eugen/
|
||||
├── chatbot.py # Main entry point
|
||||
├── setup_wizard.py # Interactive setup wizard
|
||||
├── test_credentials.py # Credential validation tool
|
||||
├── config.py # Configuration management
|
||||
├── gui.py # Dashboard GUI
|
||||
├── ai_provider.py # Perplexity API integration
|
||||
|
|
@ -102,12 +104,32 @@ python -m venv venv
|
|||
# Install dependencies
|
||||
pip install -r requirements.txt
|
||||
|
||||
# Run interactive setup wizard
|
||||
python setup_wizard.py
|
||||
|
||||
# Test credentials (recommended before first run)
|
||||
python test_credentials.py
|
||||
|
||||
# Run the bot
|
||||
python chatbot.py
|
||||
```
|
||||
|
||||
## Testing API Keys
|
||||
## Testing Credentials
|
||||
|
||||
Use the credential validator for comprehensive testing:
|
||||
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
This tool:
|
||||
- Tests Twitch OAuth token with IRC authentication
|
||||
- Validates Perplexity API key and model access
|
||||
- Provides detailed error diagnostics
|
||||
- Suggests fixes for common issues
|
||||
- Automatically tests fallback models (sonar-pro → sonar)
|
||||
|
||||
Manual testing:
|
||||
- **Twitch**: Test IRC connection to irc.chat.twitch.tv:6667
|
||||
- **Perplexity**: POST to https://api.perplexity.ai/chat/completions with a simple test message
|
||||
|
||||
|
|
|
|||
76
README.md
76
README.md
|
|
@ -80,6 +80,27 @@ PERPLEXITY_API_KEY=pplx-your_key_here
|
|||
3. Generate new API key
|
||||
4. Copy the key (should start with `pplx-`)
|
||||
|
||||
### Testing Credentials (Recommended)
|
||||
|
||||
Before running the bot, test your credentials:
|
||||
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
This will:
|
||||
- Validate your Twitch OAuth token with detailed diagnostics
|
||||
- Test your Perplexity API key and check model access
|
||||
- Provide specific error messages and fixes for common issues
|
||||
- Automatically detect if `sonar-pro` is unavailable and suggest `sonar` fallback
|
||||
|
||||
**Example output:**
|
||||
```
|
||||
✓ Twitch IRC: PASS
|
||||
✓ Perplexity API: PASS
|
||||
🎉 All credentials valid! Bot is ready to run.
|
||||
```
|
||||
|
||||
### Running the Bot
|
||||
|
||||
```bash
|
||||
|
|
@ -105,6 +126,8 @@ Eugen: @User For bed leveling, start by...
|
|||
```
|
||||
eugen/
|
||||
├── chatbot.py # Main entry point
|
||||
├── setup_wizard.py # Interactive setup tool
|
||||
├── test_credentials.py # Credential validator
|
||||
├── config.py # Configuration management
|
||||
├── gui.py # Dashboard GUI
|
||||
├── ai_provider.py # Perplexity API integration
|
||||
|
|
@ -135,20 +158,51 @@ The bot is built with:
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
**Bot doesn't respond:**
|
||||
- Check that .env has correct OAuth token and API key
|
||||
- Verify bot is in the correct channel
|
||||
- Check logs/eugen.log for errors
|
||||
### Quick Diagnosis
|
||||
|
||||
**API errors:**
|
||||
- Verify Perplexity API key is valid
|
||||
- Check your API credits at perplexity.ai
|
||||
- Enable DEBUG_MODE=true in .env for detailed logs
|
||||
**First step: Run the credential validator**
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
This will identify exactly what's wrong and provide specific fixes.
|
||||
|
||||
### Common Issues
|
||||
|
||||
**Twitch OAuth Token Invalid:**
|
||||
- ✗ Error: `Login authentication failed`
|
||||
- **Fix:**
|
||||
1. Go to https://twitchtokengenerator.com
|
||||
2. Select "Bot Chat Token"
|
||||
3. Make sure you're logged in as the bot account
|
||||
4. Copy the new token (including `oauth:` prefix)
|
||||
5. Update `TWITCH_OAUTH_TOKEN` in `.env`
|
||||
|
||||
**Bot nickname mismatch:**
|
||||
- Token must be generated by the same account as `TWITCH_BOT_NICKNAME`
|
||||
- If bot nickname is `EugenBot`, you must be logged into Twitch as `EugenBot` when generating the token
|
||||
|
||||
**Perplexity Model Not Available:**
|
||||
- ✗ Error: `400 Bad Request` or model not accessible
|
||||
- **Fix:**
|
||||
- Your API key might not have access to `sonar-pro`
|
||||
- The setup wizard will automatically suggest `sonar` as fallback
|
||||
- Or manually change `PERPLEXITY_MODEL=sonar` in `.env`
|
||||
|
||||
**Bot doesn't respond in chat:**
|
||||
- Run `python test_credentials.py` to verify credentials
|
||||
- Check that bot is in the correct channel
|
||||
- Check `logs/eugen.log` for errors
|
||||
- Verify bot was mentioned correctly (`@Eugen` or `Eugen:`)
|
||||
|
||||
**IRC connection failed:**
|
||||
- Verify internet connection
|
||||
- Check firewall settings for port 6667
|
||||
- Regenerate Twitch OAuth token if expired
|
||||
- Check internet connection
|
||||
- Verify firewall allows port 6667
|
||||
- Run credential validator for detailed diagnostics
|
||||
|
||||
**API rate limits:**
|
||||
- Check your Perplexity API credits at https://www.perplexity.ai/settings/api
|
||||
- Enable `DEBUG_MODE=true` in `.env` for detailed API logs
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
|||
279
TROUBLESHOOTING.md
Normal file
279
TROUBLESHOOTING.md
Normal file
|
|
@ -0,0 +1,279 @@
|
|||
# Eugen Bot - Troubleshooting Guide
|
||||
|
||||
Quick reference for diagnosing and fixing common issues with the Eugen Twitch bot.
|
||||
|
||||
## Quick Start Diagnostic Tool
|
||||
|
||||
**Before anything else**, run the credential validator:
|
||||
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
This tool will:
|
||||
- Test your Twitch OAuth token
|
||||
- Validate your Perplexity API key
|
||||
- Check model availability (sonar-pro vs sonar)
|
||||
- Provide specific error messages
|
||||
- Suggest exact fixes
|
||||
|
||||
---
|
||||
|
||||
## Common Error Messages
|
||||
|
||||
### 1. Twitch IRC Authentication Failed
|
||||
|
||||
**Error Output:**
|
||||
```
|
||||
IRC EVENT: privnotice | Source: tmi.twitch.tv | Args: ['Login authentication failed']
|
||||
```
|
||||
|
||||
**Causes:**
|
||||
- Token is expired or invalid
|
||||
- Token doesn't match the bot nickname
|
||||
- Bot account is banned/suspended
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. **Verify Bot Nickname Match**
|
||||
- If `TWITCH_BOT_NICKNAME=Eugen`, you must generate the token while logged into Twitch as `Eugen`
|
||||
- Token and bot nickname MUST match the same account
|
||||
|
||||
2. **Generate New Token**
|
||||
```
|
||||
1. Go to: https://twitchtokengenerator.com
|
||||
2. Log into Twitch as the bot account
|
||||
3. Select "Bot Chat Token"
|
||||
4. Copy the full token (including oauth: prefix)
|
||||
5. Update .env file:
|
||||
TWITCH_OAUTH_TOKEN=oauth:your_new_token_here
|
||||
```
|
||||
|
||||
3. **Test the Token**
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
### 2. Perplexity API 400 Bad Request
|
||||
|
||||
**Error Output:**
|
||||
```
|
||||
⚠ Unerwartete Antwort: 400
|
||||
```
|
||||
|
||||
**Causes:**
|
||||
- API key doesn't have access to `sonar-pro` model
|
||||
- Invalid request format
|
||||
- Model not available on your plan
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. **Use Model Fallback**
|
||||
- The setup wizard automatically tries `sonar` if `sonar-pro` fails
|
||||
- Manually update `.env`:
|
||||
```
|
||||
PERPLEXITY_MODEL=sonar
|
||||
```
|
||||
|
||||
2. **Verify API Key**
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
3. **Check API Credits**
|
||||
- Go to: https://www.perplexity.ai/settings/api
|
||||
- Verify your account has credits
|
||||
- Check API key is active
|
||||
|
||||
### 3. Perplexity API 401 Unauthorized
|
||||
|
||||
**Error Output:**
|
||||
```
|
||||
✗ Perplexity API-Key ist ungültig (401 Unauthorized)
|
||||
```
|
||||
|
||||
**Causes:**
|
||||
- Invalid API key
|
||||
- API key was revoked
|
||||
- Typo in `.env` file
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. **Generate New API Key**
|
||||
```
|
||||
1. Go to: https://www.perplexity.ai/settings/api
|
||||
2. Create new API key
|
||||
3. Copy the key (starts with pplx-)
|
||||
4. Update .env:
|
||||
PERPLEXITY_API_KEY=pplx-your_new_key_here
|
||||
```
|
||||
|
||||
2. **Verify No Extra Spaces**
|
||||
- Check `.env` file has no spaces around the `=` sign
|
||||
- Format: `PERPLEXITY_API_KEY=pplx-abc123` (no spaces)
|
||||
|
||||
### 4. Bot Doesn't Respond in Chat
|
||||
|
||||
**Symptoms:**
|
||||
- Bot connects successfully
|
||||
- Bot joins channel
|
||||
- But doesn't respond to mentions
|
||||
|
||||
**Checklist:**
|
||||
|
||||
1. **Verify Bot is Mentioned Correctly**
|
||||
```
|
||||
✓ @Eugen how are you?
|
||||
✓ Eugen: tell me about WoW
|
||||
✓ Eugen, what's new?
|
||||
✗ eugen (lowercase doesn't work)
|
||||
```
|
||||
|
||||
2. **Check Debug Logs**
|
||||
```bash
|
||||
tail -f logs/eugen.log
|
||||
```
|
||||
Look for:
|
||||
- `Mention detected from {user}`
|
||||
- `API call to Perplexity`
|
||||
- Any error messages
|
||||
|
||||
3. **Enable Debug Mode**
|
||||
```
|
||||
DEBUG_MODE=true
|
||||
```
|
||||
Restart the bot and check logs again
|
||||
|
||||
4. **Test Credentials**
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
### 5. Connection Reset by Peer
|
||||
|
||||
**Error Output:**
|
||||
```
|
||||
IRC EVENT: disconnect | Args: ['Connection reset by peer']
|
||||
```
|
||||
|
||||
**Causes:**
|
||||
- Network interruption
|
||||
- Firewall blocking port 6667
|
||||
- Invalid authentication (see #1)
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. **Check Firewall**
|
||||
- Allow outbound connections on port 6667
|
||||
- Try temporarily disabling firewall to test
|
||||
|
||||
2. **Verify Internet Connection**
|
||||
```bash
|
||||
ping irc.chat.twitch.tv
|
||||
```
|
||||
|
||||
3. **Check OAuth Token** (most common cause)
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
### 6. Rate Limiting / API Quota Exceeded
|
||||
|
||||
**Error Output:**
|
||||
```
|
||||
429 Too Many Requests
|
||||
```
|
||||
|
||||
**Causes:**
|
||||
- Too many API calls in short time
|
||||
- Perplexity API quota exceeded
|
||||
|
||||
**Solution:**
|
||||
|
||||
1. **Check API Usage**
|
||||
- Go to: https://www.perplexity.ai/settings/api
|
||||
- View usage and limits
|
||||
|
||||
2. **Reduce Request Frequency**
|
||||
- Consider implementing cooldowns
|
||||
- Limit responses to specific users
|
||||
|
||||
3. **Wait and Retry**
|
||||
- Wait a few minutes
|
||||
- Restart the bot
|
||||
|
||||
---
|
||||
|
||||
## Diagnostic Commands
|
||||
|
||||
### Check Configuration
|
||||
```bash
|
||||
cat .env
|
||||
```
|
||||
|
||||
### View Recent Logs
|
||||
```bash
|
||||
tail -n 50 logs/eugen.log
|
||||
```
|
||||
|
||||
### View API Debug Logs
|
||||
```bash
|
||||
tail -n 50 logs/api_debug.log
|
||||
```
|
||||
|
||||
### Test Credentials
|
||||
```bash
|
||||
python test_credentials.py
|
||||
```
|
||||
|
||||
### Run Setup Wizard Again
|
||||
```bash
|
||||
python setup_wizard.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Getting Help
|
||||
|
||||
### Before Asking for Help
|
||||
|
||||
1. Run `python test_credentials.py`
|
||||
2. Check `logs/eugen.log`
|
||||
3. Enable `DEBUG_MODE=true` and restart
|
||||
4. Review this troubleshooting guide
|
||||
|
||||
### Information to Include
|
||||
|
||||
When reporting issues, include:
|
||||
- Error messages from logs
|
||||
- Output of `python test_credentials.py`
|
||||
- Contents of `.env` (REDACT secrets!)
|
||||
- Python version: `python --version`
|
||||
- OS: Windows/Linux/Mac
|
||||
|
||||
### Resources
|
||||
|
||||
- **GitHub Issues**: https://github.com/Kenearos/KI-Chat-Bot-Eugen/issues
|
||||
- **Twitch Token Generator**: https://twitchtokengenerator.com
|
||||
- **Perplexity API**: https://www.perplexity.ai/settings/api
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### File Locations
|
||||
- Configuration: `.env`
|
||||
- Main log: `logs/eugen.log`
|
||||
- API debug: `logs/api_debug.log`
|
||||
- Conversations: `data/conversations/`
|
||||
|
||||
### Required Credentials
|
||||
- Twitch OAuth Token (starts with `oauth:`)
|
||||
- Twitch Bot Nickname (must match token account)
|
||||
- Twitch Channel (starts with `#`)
|
||||
- Perplexity API Key (starts with `pplx-`)
|
||||
|
||||
### Testing Tools
|
||||
- `python setup_wizard.py` - Interactive setup
|
||||
- `python test_credentials.py` - Validate credentials
|
||||
- `python chatbot.py` - Run the bot
|
||||
145
setup_wizard.py
145
setup_wizard.py
|
|
@ -69,20 +69,47 @@ async def validate_twitch_token(token, bot_nickname):
|
|||
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))
|
||||
sock.settimeout(10)
|
||||
|
||||
# Connect
|
||||
try:
|
||||
sock.connect(('irc.chat.twitch.tv', 6667))
|
||||
except socket.timeout:
|
||||
print_warning("Verbindung zu Twitch IRC hat zu lange gedauert")
|
||||
print_info("Prüfe deine Internetverbindung und Firewall-Einstellungen")
|
||||
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
|
||||
return True
|
||||
|
||||
# Send authentication
|
||||
sock.send(f"PASS {token}\r\n".encode())
|
||||
sock.send(f"NICK {bot_nickname}\r\n".encode())
|
||||
|
||||
response = sock.recv(1024).decode()
|
||||
# Receive response
|
||||
response = sock.recv(2048).decode()
|
||||
|
||||
if "Login authentication failed" in response:
|
||||
print_error("Twitch OAuth Token ist ungültig!")
|
||||
print_info("\nMögliche Gründe:")
|
||||
print(f" • Token ist abgelaufen oder ungültig")
|
||||
print(f" • Token passt nicht zum Bot-Namen '{bot_nickname}'")
|
||||
print(f" • Account ist gesperrt oder eingeschränkt")
|
||||
print_info("\nLösung:")
|
||||
print(f" → Gehe zu: https://twitchtokengenerator.com")
|
||||
print(f" → Stelle sicher, dass du als '{bot_nickname}' eingeloggt bist")
|
||||
print(f" → Generiere einen neuen 'Bot Chat Token'")
|
||||
return False
|
||||
|
||||
print_success("Twitch-Verbindung erfolgreich!")
|
||||
if ":tmi.twitch.tv 001" in response or "Welcome" in response:
|
||||
print_success("Twitch-Verbindung erfolgreich!")
|
||||
return True
|
||||
|
||||
# Ambiguous - probably OK
|
||||
if "authentication failed" not in response.lower():
|
||||
print_success("Twitch-Verbindung scheinbar erfolgreich (kein Fehler erkannt)")
|
||||
return True
|
||||
|
||||
print_warning(f"Unerwartete Antwort von Twitch IRC")
|
||||
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
|
|
@ -93,8 +120,8 @@ async def validate_twitch_token(token, bot_nickname):
|
|||
|
||||
async def validate_perplexity_key(api_key, model="sonar-pro"):
|
||||
"""
|
||||
Validate Perplexity API key with test request
|
||||
|
||||
Validate Perplexity API key with test request and model fallback
|
||||
|
||||
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.
|
||||
|
|
@ -104,40 +131,73 @@ async def validate_perplexity_key(api_key, model="sonar-pro"):
|
|||
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
|
||||
tuple: (bool success, bool should_retry, str recommended_model)
|
||||
success indicates if validation passed,
|
||||
should_retry indicates if user should be prompted to retry,
|
||||
recommended_model is the working model if different from requested
|
||||
"""
|
||||
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"
|
||||
}
|
||||
)
|
||||
# Test with multiple models
|
||||
models_to_test = [model]
|
||||
if model != "sonar":
|
||||
models_to_test.append("sonar")
|
||||
|
||||
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)
|
||||
for test_model in models_to_test:
|
||||
try:
|
||||
print_info(f"Validiere Perplexity API-Key mit Modell '{test_model}'...")
|
||||
async with httpx.AsyncClient(timeout=10.0) as client:
|
||||
response = await client.post(
|
||||
"https://api.perplexity.ai/chat/completions",
|
||||
json={
|
||||
"model": test_model,
|
||||
"messages": [{"role": "user", "content": "test"}],
|
||||
"max_tokens": 10
|
||||
},
|
||||
headers={
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
)
|
||||
|
||||
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)
|
||||
if response.status_code == 200:
|
||||
print_success(f"Perplexity API-Key ist gültig mit Modell '{test_model}'!")
|
||||
if test_model != model:
|
||||
print_warning(f"Hinweis: Modell '{model}' nicht verfügbar, verwende '{test_model}'")
|
||||
return (True, False, test_model)
|
||||
elif response.status_code == 401:
|
||||
print_error("Perplexity API-Key ist ungültig (401 Unauthorized)!")
|
||||
print_info("Bitte überprüfe deinen API-Key auf: https://www.perplexity.ai/settings/api")
|
||||
return (False, True, None)
|
||||
elif response.status_code == 400:
|
||||
try:
|
||||
error_data = response.json()
|
||||
error_msg = error_data.get("error", {}).get("message", "Unbekannter Fehler")
|
||||
|
||||
# Check if model access issue
|
||||
if "model" in error_msg.lower() and test_model != models_to_test[-1]:
|
||||
print_warning(f"Modell '{test_model}' nicht verfügbar: {error_msg}")
|
||||
print_info("Versuche Fallback-Modell...")
|
||||
continue
|
||||
else:
|
||||
print_warning(f"400 Fehler: {error_msg}")
|
||||
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
|
||||
return (True, False, model)
|
||||
except:
|
||||
print_warning(f"Unerwartete Antwort: {response.status_code}")
|
||||
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
|
||||
return (True, False, model)
|
||||
else:
|
||||
print_warning(f"Unerwartete Antwort: {response.status_code}")
|
||||
print_info("Fahre trotzdem fort - bitte später manuell prüfen!")
|
||||
return (True, False, model)
|
||||
|
||||
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, model)
|
||||
|
||||
# All models failed
|
||||
print_error("Alle Modelle fehlgeschlagen!")
|
||||
return (False, True, None)
|
||||
|
||||
|
||||
def create_env_file(config):
|
||||
|
|
@ -279,14 +339,17 @@ async def run_wizard():
|
|||
print(" → Kopiere den Key (beginnt mit 'pplx-...')")
|
||||
print()
|
||||
|
||||
recommended_model = "sonar-pro"
|
||||
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)
|
||||
success, should_retry, working_model = await validate_perplexity_key(api_key, "sonar-pro")
|
||||
if success:
|
||||
if working_model:
|
||||
recommended_model = working_model
|
||||
break
|
||||
|
||||
|
||||
if should_retry:
|
||||
retry = input("\nErneut versuchen? (j/n): ")
|
||||
if retry.lower() != 'j':
|
||||
|
|
@ -302,7 +365,7 @@ async def run_wizard():
|
|||
if advanced:
|
||||
config['PERPLEXITY_MODEL'] = get_input(
|
||||
"Perplexity Modell",
|
||||
default="sonar-pro"
|
||||
default=recommended_model
|
||||
)
|
||||
config['MAX_TOKENS'] = get_input(
|
||||
"Max Tokens pro Antwort",
|
||||
|
|
@ -317,7 +380,7 @@ async def run_wizard():
|
|||
default="1"
|
||||
)
|
||||
else:
|
||||
config['PERPLEXITY_MODEL'] = "sonar-pro"
|
||||
config['PERPLEXITY_MODEL'] = recommended_model
|
||||
config['MAX_TOKENS'] = "450"
|
||||
config['DEBUG_MODE'] = "false"
|
||||
config['CONTEXT_RETENTION_HOURS'] = "1"
|
||||
|
|
|
|||
336
test_credentials.py
Normal file
336
test_credentials.py
Normal file
|
|
@ -0,0 +1,336 @@
|
|||
"""
|
||||
Credential Testing Utility for Eugen Bot
|
||||
Tests and validates Twitch OAuth tokens and Perplexity API keys
|
||||
"""
|
||||
import asyncio
|
||||
import socket
|
||||
import sys
|
||||
import os
|
||||
import httpx
|
||||
from dotenv import load_dotenv
|
||||
|
||||
|
||||
class Colors:
|
||||
"""ANSI color codes"""
|
||||
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}{'='*70}{Colors.ENDC}")
|
||||
print(f"{Colors.HEADER}{Colors.BOLD}{text.center(70)}{Colors.ENDC}")
|
||||
print(f"{Colors.HEADER}{Colors.BOLD}{'='*70}{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 test_twitch_token(token, nickname):
|
||||
"""
|
||||
Test Twitch OAuth token with detailed diagnostics
|
||||
|
||||
Args:
|
||||
token (str): OAuth token
|
||||
nickname (str): Bot nickname
|
||||
|
||||
Returns:
|
||||
bool: True if valid
|
||||
"""
|
||||
print_header("TESTING TWITCH CREDENTIALS")
|
||||
|
||||
# Check token format
|
||||
if not token:
|
||||
print_error("Token is empty!")
|
||||
print_info("Get a token from: https://twitchtokengenerator.com")
|
||||
return False
|
||||
|
||||
if not token.startswith("oauth:"):
|
||||
print_warning(f"Token doesn't start with 'oauth:' (got: {token[:10]}...)")
|
||||
print_info("Token should look like: oauth:abcd1234...")
|
||||
return False
|
||||
|
||||
print_info(f"Token format: ✓ Starts with 'oauth:'")
|
||||
print_info(f"Token length: {len(token)} characters")
|
||||
print_info(f"Bot nickname: {nickname}")
|
||||
|
||||
# Test IRC connection
|
||||
print_info("\nConnecting to Twitch IRC (irc.chat.twitch.tv:6667)...")
|
||||
|
||||
try:
|
||||
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
|
||||
sock.settimeout(10)
|
||||
|
||||
# Connect
|
||||
try:
|
||||
sock.connect(('irc.chat.twitch.tv', 6667))
|
||||
print_success("Connected to IRC server")
|
||||
except socket.timeout:
|
||||
print_error("Connection timed out!")
|
||||
print_info("Check your internet connection and firewall settings")
|
||||
return False
|
||||
except Exception as e:
|
||||
print_error(f"Connection failed: {e}")
|
||||
return False
|
||||
|
||||
# Send authentication
|
||||
print_info("Sending authentication...")
|
||||
sock.send(f"PASS {token}\r\n".encode())
|
||||
sock.send(f"NICK {nickname}\r\n".encode())
|
||||
|
||||
# Wait for response
|
||||
response = ""
|
||||
try:
|
||||
response = sock.recv(2048).decode()
|
||||
except socket.timeout:
|
||||
print_error("No response from server (timeout)")
|
||||
return False
|
||||
|
||||
# Parse response
|
||||
print_info(f"\nServer response received ({len(response)} bytes)")
|
||||
|
||||
if "Login authentication failed" in response:
|
||||
print_error("AUTHENTICATION FAILED!")
|
||||
print_info("\nPossible reasons:")
|
||||
print(f" 1. Token is expired or invalid")
|
||||
print(f" 2. Token doesn't match the bot nickname '{nickname}'")
|
||||
print(f" 3. Account that generated the token is banned/restricted")
|
||||
print_info("\nHow to fix:")
|
||||
print(f" → Go to: https://twitchtokengenerator.com")
|
||||
print(f" → Make sure you're logged into Twitch as '{nickname}'")
|
||||
print(f" → Generate a new 'Bot Chat Token'")
|
||||
print(f" → Update TWITCH_OAUTH_TOKEN in .env")
|
||||
return False
|
||||
|
||||
if ":tmi.twitch.tv 001" in response or "Welcome" in response:
|
||||
print_success("AUTHENTICATION SUCCESSFUL!")
|
||||
print_info(f"Bot '{nickname}' can connect to Twitch IRC")
|
||||
return True
|
||||
|
||||
# Ambiguous response
|
||||
print_warning("Received unexpected response:")
|
||||
for line in response.split('\r\n'):
|
||||
if line:
|
||||
print(f" {line[:100]}")
|
||||
|
||||
# If we got this far without clear failure, consider it success
|
||||
if "authentication failed" not in response.lower():
|
||||
print_success("Authentication appears successful (no error detected)")
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print_error(f"Error testing Twitch token: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False
|
||||
|
||||
|
||||
async def test_perplexity_key(api_key, model="sonar-pro"):
|
||||
"""
|
||||
Test Perplexity API key with model fallback
|
||||
|
||||
Args:
|
||||
api_key (str): Perplexity API key
|
||||
model (str): Model to test (will fallback to 'sonar' if needed)
|
||||
|
||||
Returns:
|
||||
tuple: (success, recommended_model)
|
||||
"""
|
||||
print_header("TESTING PERPLEXITY API")
|
||||
|
||||
# Check key format
|
||||
if not api_key:
|
||||
print_error("API key is empty!")
|
||||
print_info("Get a key from: https://www.perplexity.ai/settings/api")
|
||||
return False, None
|
||||
|
||||
if not api_key.startswith("pplx-"):
|
||||
print_warning(f"API key doesn't start with 'pplx-' (got: {api_key[:10]}...)")
|
||||
print_info("Key should look like: pplx-abc123...")
|
||||
|
||||
print_info(f"API key format: Starts with '{api_key[:5]}...'")
|
||||
print_info(f"API key length: {len(api_key)} characters")
|
||||
|
||||
# Test with different models
|
||||
models_to_test = [model]
|
||||
if model != "sonar":
|
||||
models_to_test.append("sonar")
|
||||
|
||||
for test_model in models_to_test:
|
||||
print_info(f"\nTesting with model: {test_model}")
|
||||
|
||||
try:
|
||||
async with httpx.AsyncClient(timeout=15.0) as client:
|
||||
response = await client.post(
|
||||
"https://api.perplexity.ai/chat/completions",
|
||||
json={
|
||||
"model": test_model,
|
||||
"messages": [{"role": "user", "content": "Say 'test successful' and nothing else"}],
|
||||
"max_tokens": 10
|
||||
},
|
||||
headers={
|
||||
"Authorization": f"Bearer {api_key}",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
)
|
||||
|
||||
print_info(f"Response status: {response.status_code}")
|
||||
|
||||
if response.status_code == 200:
|
||||
print_success(f"API KEY VALID with model '{test_model}'!")
|
||||
|
||||
# Try to parse response
|
||||
try:
|
||||
data = response.json()
|
||||
if "choices" in data and len(data["choices"]) > 0:
|
||||
content = data["choices"][0]["message"]["content"]
|
||||
print_info(f"Test response: '{content}'")
|
||||
except:
|
||||
pass
|
||||
|
||||
return True, test_model
|
||||
|
||||
elif response.status_code == 401:
|
||||
print_error("API key is INVALID (401 Unauthorized)")
|
||||
print_info("\nHow to fix:")
|
||||
print(f" → Go to: https://www.perplexity.ai/settings/api")
|
||||
print(f" → Generate a new API key")
|
||||
print(f" → Update PERPLEXITY_API_KEY in .env")
|
||||
return False, None
|
||||
|
||||
elif response.status_code == 400:
|
||||
try:
|
||||
error_data = response.json()
|
||||
error_msg = error_data.get("error", {}).get("message", "Unknown error")
|
||||
print_warning(f"400 Bad Request: {error_msg}")
|
||||
|
||||
# Check if it's a model access issue
|
||||
if "model" in error_msg.lower():
|
||||
print_info(f"Model '{test_model}' not available on your plan")
|
||||
if test_model != models_to_test[-1]:
|
||||
print_info("Trying fallback model...")
|
||||
continue
|
||||
else:
|
||||
print_info(f"Error details: {error_msg}")
|
||||
except:
|
||||
print_warning(f"400 Bad Request (couldn't parse error)")
|
||||
|
||||
# If this was the last model, fail
|
||||
if test_model == models_to_test[-1]:
|
||||
print_error("All models failed!")
|
||||
return False, None
|
||||
|
||||
elif response.status_code == 429:
|
||||
print_error("Rate limited! Too many requests.")
|
||||
print_info("Wait a few minutes and try again")
|
||||
return False, None
|
||||
|
||||
else:
|
||||
print_warning(f"Unexpected status code: {response.status_code}")
|
||||
try:
|
||||
print_info(f"Response: {response.text[:200]}")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Try next model if available
|
||||
if test_model != models_to_test[-1]:
|
||||
continue
|
||||
|
||||
return False, None
|
||||
|
||||
except httpx.TimeoutException:
|
||||
print_error("Request timed out!")
|
||||
print_info("Check your internet connection")
|
||||
return False, None
|
||||
except Exception as e:
|
||||
print_error(f"Error testing API: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return False, None
|
||||
|
||||
return False, None
|
||||
|
||||
|
||||
async def main():
|
||||
"""Main test runner"""
|
||||
print(f"""
|
||||
{Colors.HEADER}{Colors.BOLD}╔════════════════════════════════════════════════════════════════════╗
|
||||
║ EUGEN BOT - CREDENTIAL VALIDATOR ║
|
||||
║ Tests Twitch & Perplexity Credentials ║
|
||||
╚════════════════════════════════════════════════════════════════════╝{Colors.ENDC}
|
||||
""")
|
||||
|
||||
# Load .env file
|
||||
if not os.path.exists('.env'):
|
||||
print_error("No .env file found!")
|
||||
print_info("Please run: python setup_wizard.py")
|
||||
sys.exit(1)
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Get credentials
|
||||
twitch_token = os.getenv('TWITCH_OAUTH_TOKEN', '')
|
||||
twitch_nickname = os.getenv('TWITCH_BOT_NICKNAME', '')
|
||||
twitch_channel = os.getenv('TWITCH_CHANNEL', '')
|
||||
perplexity_key = os.getenv('PERPLEXITY_API_KEY', '')
|
||||
perplexity_model = os.getenv('PERPLEXITY_MODEL', 'sonar-pro')
|
||||
|
||||
print_info("Loaded configuration from .env:")
|
||||
print(f" • Bot Nickname: {twitch_nickname}")
|
||||
print(f" • Channel: {twitch_channel}")
|
||||
print(f" • Model: {perplexity_model}")
|
||||
|
||||
# Test credentials
|
||||
results = {}
|
||||
|
||||
# Test Twitch
|
||||
results['twitch'] = await test_twitch_token(twitch_token, twitch_nickname)
|
||||
|
||||
# Test Perplexity
|
||||
results['perplexity'], recommended_model = await test_perplexity_key(perplexity_key, perplexity_model)
|
||||
|
||||
# Final summary
|
||||
print_header("VALIDATION SUMMARY")
|
||||
|
||||
print(f"Twitch IRC: {'✓ PASS' if results['twitch'] else '✗ FAIL'}")
|
||||
print(f"Perplexity API: {'✓ PASS' if results['perplexity'] else '✗ FAIL'}")
|
||||
|
||||
if recommended_model and recommended_model != perplexity_model:
|
||||
print_warning(f"\nRecommendation: Update PERPLEXITY_MODEL to '{recommended_model}' in .env")
|
||||
|
||||
if all(results.values()):
|
||||
print_success("\n🎉 All credentials valid! Bot is ready to run.")
|
||||
print_info("Start the bot with: python chatbot.py")
|
||||
sys.exit(0)
|
||||
else:
|
||||
print_error("\n❌ Some credentials are invalid. Please fix and re-test.")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Loading…
Add table
Add a link
Reference in a new issue