ghygyyggy
This commit is contained in:
parent
16ae8e0841
commit
3c4c776e54
@ -443,6 +443,89 @@ async def sync_guild_commands(
|
||||
detail=f"Error syncing commands: {str(e)}"
|
||||
)
|
||||
|
||||
@router.post("/guilds/{guild_id}/test-welcome", status_code=status.HTTP_200_OK)
|
||||
async def test_welcome_message(
|
||||
guild_id: int,
|
||||
_user: dict = Depends(get_dashboard_user),
|
||||
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||
):
|
||||
"""Test the welcome message for a guild."""
|
||||
try:
|
||||
# Get welcome settings
|
||||
welcome_channel_id_str = await settings_manager.get_setting(guild_id, 'welcome_channel_id')
|
||||
welcome_message_template = await settings_manager.get_setting(guild_id, 'welcome_message', default="Welcome {user} to {server}!")
|
||||
|
||||
# Check if welcome channel is set
|
||||
if not welcome_channel_id_str or welcome_channel_id_str == "__NONE__":
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Welcome channel not configured"
|
||||
)
|
||||
|
||||
# In a real implementation, this would send a test message to the welcome channel
|
||||
# For now, we'll just return a success message with the formatted message
|
||||
formatted_message = welcome_message_template.format(
|
||||
user="@TestUser",
|
||||
username="TestUser",
|
||||
server=f"Server {guild_id}"
|
||||
)
|
||||
|
||||
return {
|
||||
"message": "Test welcome message sent",
|
||||
"channel_id": welcome_channel_id_str,
|
||||
"formatted_message": formatted_message
|
||||
}
|
||||
except HTTPException:
|
||||
# Re-raise HTTP exceptions
|
||||
raise
|
||||
except Exception as e:
|
||||
log.error(f"Error testing welcome message for guild {guild_id}: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Error testing welcome message: {str(e)}"
|
||||
)
|
||||
|
||||
@router.post("/guilds/{guild_id}/test-goodbye", status_code=status.HTTP_200_OK)
|
||||
async def test_goodbye_message(
|
||||
guild_id: int,
|
||||
_user: dict = Depends(get_dashboard_user),
|
||||
_admin: bool = Depends(verify_dashboard_guild_admin)
|
||||
):
|
||||
"""Test the goodbye message for a guild."""
|
||||
try:
|
||||
# Get goodbye settings
|
||||
goodbye_channel_id_str = await settings_manager.get_setting(guild_id, 'goodbye_channel_id')
|
||||
goodbye_message_template = await settings_manager.get_setting(guild_id, 'goodbye_message', default="{username} has left the server.")
|
||||
|
||||
# Check if goodbye channel is set
|
||||
if not goodbye_channel_id_str or goodbye_channel_id_str == "__NONE__":
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail="Goodbye channel not configured"
|
||||
)
|
||||
|
||||
# In a real implementation, this would send a test message to the goodbye channel
|
||||
# For now, we'll just return a success message with the formatted message
|
||||
formatted_message = goodbye_message_template.format(
|
||||
username="TestUser",
|
||||
server=f"Server {guild_id}"
|
||||
)
|
||||
|
||||
return {
|
||||
"message": "Test goodbye message sent",
|
||||
"channel_id": goodbye_channel_id_str,
|
||||
"formatted_message": formatted_message
|
||||
}
|
||||
except HTTPException:
|
||||
# Re-raise HTTP exceptions
|
||||
raise
|
||||
except Exception as e:
|
||||
log.error(f"Error testing goodbye message for guild {guild_id}: {e}")
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||
detail=f"Error testing goodbye message: {str(e)}"
|
||||
)
|
||||
|
||||
# --- Global Settings Endpoints ---
|
||||
|
||||
@router.get("/settings", response_model=GlobalSettings)
|
||||
|
@ -38,13 +38,17 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="nav-icon"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"></rect><line x1="8" y1="21" x2="16" y2="21"></line><line x1="12" y1="17" x2="12" y2="21"></line></svg>
|
||||
Server Settings
|
||||
</a>
|
||||
<a href="#ai-settings" class="nav-item" data-section="ai-settings-section">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="nav-icon"><path d="M12 2a10 10 0 1 0 10 10H12V2z"></path><path d="M20 12a8 8 0 1 0-16 0"></path><path d="M12 12v10"></path></svg>
|
||||
AI Settings
|
||||
<a href="#welcome-module" class="nav-item" data-section="welcome-module-section">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="nav-icon"><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z"></path><polyline points="9 22 9 12 15 12 15 22"></polyline></svg>
|
||||
Welcome/Leave
|
||||
</a>
|
||||
<a href="#conversations" class="nav-item" data-section="conversations-section">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="nav-icon"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
|
||||
Conversations
|
||||
<a href="#modules-settings" class="nav-item" data-section="modules-settings-section">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="nav-icon"><path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"></path><rect x="8" y="2" width="8" height="4" rx="1" ry="1"></rect></svg>
|
||||
Modules
|
||||
</a>
|
||||
<a href="#permissions-settings" class="nav-item" data-section="permissions-settings-section">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="nav-icon"><path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"></path></svg>
|
||||
Permissions
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-footer">
|
||||
@ -102,7 +106,18 @@
|
||||
<p id="prefix-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Welcome/Leave Module Section -->
|
||||
<div id="welcome-module-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Welcome & Leave Messages</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="welcome-settings-form" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Welcome Messages</h3>
|
||||
@ -124,6 +139,7 @@
|
||||
<div class="btn-group">
|
||||
<button id="save-welcome-button" class="btn btn-primary">Save Welcome Settings</button>
|
||||
<button id="disable-welcome-button" class="btn btn-warning">Disable Welcome</button>
|
||||
<button id="test-welcome-button" class="btn btn-secondary">Test Welcome Message</button>
|
||||
</div>
|
||||
<p id="welcome-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
@ -149,10 +165,22 @@
|
||||
<div class="btn-group">
|
||||
<button id="save-goodbye-button" class="btn btn-primary">Save Goodbye Settings</button>
|
||||
<button id="disable-goodbye-button" class="btn btn-warning">Disable Goodbye</button>
|
||||
<button id="test-goodbye-button" class="btn btn-secondary">Test Goodbye Message</button>
|
||||
</div>
|
||||
<p id="goodbye-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modules Settings Section -->
|
||||
<div id="modules-settings-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Manage Bot Modules</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="modules-settings-form" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Enabled Modules (Cogs)</h3>
|
||||
@ -170,7 +198,18 @@
|
||||
</div>
|
||||
<p id="cogs-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Permissions Settings Section -->
|
||||
<div id="permissions-settings-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Command Permissions</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="permissions-settings-form" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Command Permissions</h3>
|
||||
@ -202,262 +241,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI Settings Section -->
|
||||
<div id="ai-settings-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">AI Settings</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">General AI Settings</h3>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ai-model-select">AI Model:</label>
|
||||
<select id="ai-model-select" class="w-full">
|
||||
<option value="openai/gpt-3.5-turbo">GPT-3.5 Turbo</option>
|
||||
<option value="openai/gpt-4">GPT-4</option>
|
||||
<option value="anthropic/claude-3-opus">Claude 3 Opus</option>
|
||||
<option value="anthropic/claude-3-sonnet">Claude 3 Sonnet</option>
|
||||
<option value="google/gemini-2.5-flash-preview">Gemini 2.5 Flash</option>
|
||||
<option value="google/gemini-2.5-pro-preview">Gemini 2.5 Pro</option>
|
||||
<!-- More models will be populated dynamically if available -->
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ai-temperature">Temperature: <span id="temperature-value">0.7</span></label>
|
||||
<input type="range" id="ai-temperature" min="0" max="2" step="0.1" value="0.7" class="w-full">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ai-max-tokens">Max Tokens:</label>
|
||||
<input type="number" id="ai-max-tokens" min="100" max="8000" step="100" value="1000" class="w-full">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="ai-reasoning-enabled">
|
||||
Enable Reasoning
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-group" id="reasoning-effort-group">
|
||||
<label for="ai-reasoning-effort">Reasoning Effort:</label>
|
||||
<select id="ai-reasoning-effort" class="w-full">
|
||||
<option value="low">Low</option>
|
||||
<option value="medium" selected>Medium</option>
|
||||
<option value="high">High</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="ai-web-search-enabled">
|
||||
Enable Web Search
|
||||
</label>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="save-ai-settings-button" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>
|
||||
Save AI Settings
|
||||
</button>
|
||||
<button id="reset-ai-settings-button" class="btn btn-warning">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path></svg>
|
||||
Reset to Defaults
|
||||
</button>
|
||||
</div>
|
||||
<p id="ai-settings-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Character Settings</h3>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ai-character">Character Name:</label>
|
||||
<input type="text" id="ai-character" placeholder="e.g., Kasane Teto" class="w-full">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="ai-character-info">Character Information:</label>
|
||||
<textarea id="ai-character-info" rows="4" placeholder="Describe the character's personality, background, etc." class="w-full"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="checkbox-label">
|
||||
<input type="checkbox" id="ai-character-breakdown">
|
||||
Enable Character Breakdown
|
||||
</label>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="save-character-settings-button" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>
|
||||
Save Character Settings
|
||||
</button>
|
||||
<button id="clear-character-settings-button" class="btn btn-warning">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
|
||||
Clear Character
|
||||
</button>
|
||||
</div>
|
||||
<p id="character-settings-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">System Prompt</h3>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<textarea id="ai-system-prompt" rows="6" placeholder="Enter a system prompt to guide the AI's behavior..." class="w-full"></textarea>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="save-system-prompt-button" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>
|
||||
Save System Prompt
|
||||
</button>
|
||||
<button id="reset-system-prompt-button" class="btn btn-warning">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M3 12a9 9 0 1 0 9-9 9.75 9.75 0 0 0-6.74 2.74L3 8"></path><path d="M3 3v5h5"></path></svg>
|
||||
Reset to Default
|
||||
</button>
|
||||
</div>
|
||||
<p id="system-prompt-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Custom Instructions</h3>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<textarea id="ai-custom-instructions" rows="6" placeholder="Enter custom instructions for the AI..." class="w-full"></textarea>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="save-custom-instructions-button" class="btn btn-primary">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"></path><polyline points="17 21 17 13 7 13 7 21"></polyline><polyline points="7 3 7 8 15 8"></polyline></svg>
|
||||
Save Custom Instructions
|
||||
</button>
|
||||
<button id="clear-custom-instructions-button" class="btn btn-warning">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path><line x1="10" y1="11" x2="10" y2="17"></line><line x1="14" y1="11" x2="14" y2="17"></line></svg>
|
||||
Clear Instructions
|
||||
</button>
|
||||
</div>
|
||||
<p id="custom-instructions-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Conversations Section -->
|
||||
<div id="conversations-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">AI Conversations</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h3 class="card-title mb-0">Your Conversations</h3>
|
||||
<button id="new-conversation-button" class="btn btn-primary btn-sm">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-1"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>
|
||||
New Conversation
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group mt-4">
|
||||
<div class="search-container">
|
||||
<input type="text" id="conversation-search" placeholder="Search conversations..." class="w-full">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="conversations-list-container border rounded p-0 mb-4" style="max-height: 300px; overflow-y: auto;">
|
||||
<div id="conversations-list">
|
||||
<!-- Will be populated by JS -->
|
||||
<div class="no-conversations p-4 text-center text-gray">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1" stroke-linecap="round" stroke-linejoin="round" style="margin: 0 auto 1rem;"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"></path></svg>
|
||||
<p>No conversations found.</p>
|
||||
<button id="start-conversation-button" class="btn btn-primary btn-sm mt-2">Start a new conversation</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="conversation-detail" class="card" style="display: none;">
|
||||
<div class="card-header d-flex justify-content-between align-items-center">
|
||||
<h3 id="conversation-title" class="card-title mb-0">Conversation Title</h3>
|
||||
<div class="conversation-actions">
|
||||
<button id="rename-conversation-button" class="btn btn-secondary btn-sm">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M11 4H4a2 2 0 0 0-2 2v14a2 2 0 0 0 2 2h14a2 2 0 0 0 2-2v-7"></path><path d="M18.5 2.5a2.121 2.121 0 0 1 3 3L12 15l-4 1 1-4 9.5-9.5z"></path></svg>
|
||||
</button>
|
||||
<button id="export-conversation-button" class="btn btn-secondary btn-sm">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
||||
</button>
|
||||
<button id="delete-conversation-button" class="btn btn-danger btn-sm">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M3 6h18"></path><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="conversation-messages p-4" id="conversation-messages" style="max-height: 500px; overflow-y: auto;">
|
||||
<!-- Will be populated by JS -->
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal for renaming conversations -->
|
||||
<div id="rename-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Rename Conversation</h3>
|
||||
<button class="modal-close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="new-conversation-title">New Title:</label>
|
||||
<input type="text" id="new-conversation-title" placeholder="Enter new title" class="w-full">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="cancel-rename-button" class="btn btn-secondary">Cancel</button>
|
||||
<button id="confirm-rename-button" class="btn btn-primary">Rename</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal for creating new conversations -->
|
||||
<div id="new-conversation-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Create New Conversation</h3>
|
||||
<button class="modal-close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label for="new-conversation-name">Conversation Title:</label>
|
||||
<input type="text" id="new-conversation-name" placeholder="Enter conversation title" class="w-full">
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="cancel-create-button" class="btn btn-secondary">Cancel</button>
|
||||
<button id="create-conversation-button" class="btn btn-primary">Create</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Delete confirmation modal -->
|
||||
<div id="delete-confirm-modal" class="modal">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Delete Conversation</h3>
|
||||
<button class="modal-close">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<p>Are you sure you want to delete this conversation? This action cannot be undone.</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button id="cancel-delete-button" class="btn btn-secondary">Cancel</button>
|
||||
<button id="confirm-delete-button" class="btn btn-danger">Delete</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript files -->
|
||||
<script src="js/utils.js"></script>
|
||||
|
@ -337,9 +337,6 @@ function initDropdowns() {
|
||||
function loadDashboardData() {
|
||||
// Load guilds for server select
|
||||
loadGuilds();
|
||||
|
||||
// Load global settings
|
||||
loadGlobalSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -431,6 +428,10 @@ function loadGuilds() {
|
||||
*/
|
||||
function loadGuildSettings(guildId) {
|
||||
const settingsForm = document.getElementById('settings-form');
|
||||
const welcomeSettingsForm = document.getElementById('welcome-settings-form');
|
||||
const modulesSettingsForm = document.getElementById('modules-settings-form');
|
||||
const permissionsSettingsForm = document.getElementById('permissions-settings-form');
|
||||
|
||||
if (!settingsForm) return;
|
||||
|
||||
// Show loading state
|
||||
@ -440,7 +441,13 @@ function loadGuildSettings(guildId) {
|
||||
loadingContainer.style.textAlign = 'center';
|
||||
loadingContainer.style.padding = '2rem';
|
||||
|
||||
// Hide all forms
|
||||
settingsForm.style.display = 'none';
|
||||
if (welcomeSettingsForm) welcomeSettingsForm.style.display = 'none';
|
||||
if (modulesSettingsForm) modulesSettingsForm.style.display = 'none';
|
||||
if (permissionsSettingsForm) permissionsSettingsForm.style.display = 'none';
|
||||
|
||||
// Add loading indicator to server settings section
|
||||
settingsForm.parentNode.insertBefore(loadingContainer, settingsForm);
|
||||
|
||||
// Fetch guild settings from API
|
||||
@ -449,16 +456,22 @@ function loadGuildSettings(guildId) {
|
||||
// Remove loading container
|
||||
loadingContainer.remove();
|
||||
|
||||
// Show settings form
|
||||
// Show all settings forms
|
||||
settingsForm.style.display = 'block';
|
||||
if (welcomeSettingsForm) welcomeSettingsForm.style.display = 'block';
|
||||
if (modulesSettingsForm) modulesSettingsForm.style.display = 'block';
|
||||
if (permissionsSettingsForm) permissionsSettingsForm.style.display = 'block';
|
||||
|
||||
// Populate form with settings
|
||||
// Populate forms with settings
|
||||
populateGuildSettings(settings);
|
||||
|
||||
// Load additional data
|
||||
loadGuildChannels(guildId);
|
||||
loadGuildRoles(guildId);
|
||||
loadGuildCommands(guildId);
|
||||
|
||||
// Set up welcome/leave message test buttons
|
||||
setupWelcomeLeaveTestButtons(guildId);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading guild settings:', error);
|
||||
@ -881,292 +894,101 @@ function removeCommandPermission(guildId, command, roleId) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Load global AI settings
|
||||
* Set up welcome/leave message test buttons
|
||||
* @param {string} guildId - The guild ID
|
||||
*/
|
||||
function loadGlobalSettings() {
|
||||
const aiSettingsSection = document.getElementById('ai-settings-section');
|
||||
if (!aiSettingsSection) return;
|
||||
function setupWelcomeLeaveTestButtons(guildId) {
|
||||
// Welcome message test button
|
||||
const testWelcomeButton = document.getElementById('test-welcome-button');
|
||||
if (testWelcomeButton) {
|
||||
testWelcomeButton.addEventListener('click', () => {
|
||||
// Show loading state
|
||||
testWelcomeButton.disabled = true;
|
||||
testWelcomeButton.classList.add('btn-loading');
|
||||
|
||||
// Show loading state
|
||||
const loadingContainer = document.createElement('div');
|
||||
loadingContainer.className = 'loading-container';
|
||||
loadingContainer.innerHTML = '<div class="loading-spinner"></div><p>Loading AI settings...</p>';
|
||||
loadingContainer.style.textAlign = 'center';
|
||||
loadingContainer.style.padding = '2rem';
|
||||
// Send test request to API
|
||||
API.post(`/dashboard/api/guilds/${guildId}/test-welcome`)
|
||||
.then(response => {
|
||||
console.log('Test welcome message response:', response);
|
||||
|
||||
aiSettingsSection.prepend(loadingContainer);
|
||||
// Show success message with formatted message
|
||||
Toast.success('Test welcome message sent!');
|
||||
|
||||
// Fetch global settings from API
|
||||
API.get('/dashboard/api/settings')
|
||||
.then(settings => {
|
||||
// Remove loading container
|
||||
loadingContainer.remove();
|
||||
// Show formatted message in feedback area
|
||||
const welcomeFeedback = document.getElementById('welcome-feedback');
|
||||
if (welcomeFeedback) {
|
||||
welcomeFeedback.innerHTML = `
|
||||
<div class="mt-4 p-3 border rounded bg-light">
|
||||
<strong>Test Message:</strong>
|
||||
<p class="mb-0">${response.formatted_message}</p>
|
||||
<small class="text-muted">Sent to channel ID: ${response.channel_id}</small>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error testing welcome message:', error);
|
||||
|
||||
console.log('Loaded AI settings:', settings);
|
||||
|
||||
// Populate AI model select
|
||||
const modelSelect = document.getElementById('ai-model-select');
|
||||
if (modelSelect && settings.model) {
|
||||
modelSelect.value = settings.model;
|
||||
}
|
||||
|
||||
// Populate temperature slider
|
||||
const temperatureSlider = document.getElementById('ai-temperature');
|
||||
const temperatureValue = document.getElementById('temperature-value');
|
||||
if (temperatureSlider && temperatureValue) {
|
||||
const temp = settings.temperature !== undefined ? settings.temperature : 0.7;
|
||||
temperatureSlider.value = temp;
|
||||
temperatureValue.textContent = temp;
|
||||
|
||||
// Add input event for live update
|
||||
temperatureSlider.addEventListener('input', () => {
|
||||
temperatureValue.textContent = temperatureSlider.value;
|
||||
// Show error message
|
||||
if (error.status === 400) {
|
||||
Toast.error('Welcome channel not configured. Please set a welcome channel first.');
|
||||
} else {
|
||||
Toast.error('Failed to test welcome message. Please try again.');
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// Remove loading state
|
||||
testWelcomeButton.disabled = false;
|
||||
testWelcomeButton.classList.remove('btn-loading');
|
||||
});
|
||||
}
|
||||
|
||||
// Populate max tokens
|
||||
const maxTokensInput = document.getElementById('ai-max-tokens');
|
||||
if (maxTokensInput) {
|
||||
const maxTokens = settings.max_tokens !== undefined ? settings.max_tokens : 1000;
|
||||
maxTokensInput.value = maxTokens;
|
||||
}
|
||||
|
||||
// Populate character settings
|
||||
const characterInput = document.getElementById('ai-character');
|
||||
const characterInfoInput = document.getElementById('ai-character-info');
|
||||
|
||||
if (characterInput) {
|
||||
characterInput.value = settings.character || '';
|
||||
}
|
||||
|
||||
if (characterInfoInput) {
|
||||
characterInfoInput.value = settings.character_info || '';
|
||||
}
|
||||
|
||||
// Populate system prompt
|
||||
const systemPromptInput = document.getElementById('ai-system-prompt');
|
||||
if (systemPromptInput) {
|
||||
systemPromptInput.value = settings.system_message || '';
|
||||
}
|
||||
|
||||
// Populate custom instructions
|
||||
const customInstructionsInput = document.getElementById('ai-custom-instructions');
|
||||
if (customInstructionsInput) {
|
||||
customInstructionsInput.value = settings.custom_instructions || '';
|
||||
}
|
||||
|
||||
// Set up save buttons
|
||||
setupAISettingsSaveButtons(settings);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error loading global settings:', error);
|
||||
loadingContainer.innerHTML = '<p class="text-danger">Error loading AI settings. Please try again.</p>';
|
||||
Toast.error('Failed to load AI settings. Please try again.');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up AI settings save buttons
|
||||
* @param {Object} initialSettings - The initial settings
|
||||
*/
|
||||
function setupAISettingsSaveButtons(initialSettings) {
|
||||
// AI Settings save button
|
||||
const saveAISettingsButton = document.getElementById('save-ai-settings-button');
|
||||
if (saveAISettingsButton) {
|
||||
saveAISettingsButton.addEventListener('click', () => {
|
||||
const modelSelect = document.getElementById('ai-model-select');
|
||||
const temperatureSlider = document.getElementById('ai-temperature');
|
||||
const maxTokensInput = document.getElementById('ai-max-tokens');
|
||||
const reasoningEnabled = document.getElementById('ai-reasoning-enabled');
|
||||
const reasoningEffort = document.getElementById('ai-reasoning-effort');
|
||||
const webSearchEnabled = document.getElementById('ai-web-search-enabled');
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
model: modelSelect ? modelSelect.value : initialSettings.model,
|
||||
temperature: temperatureSlider ? parseFloat(temperatureSlider.value) : initialSettings.temperature,
|
||||
max_tokens: maxTokensInput ? parseInt(maxTokensInput.value) : initialSettings.max_tokens
|
||||
};
|
||||
|
||||
// Add optional settings if they exist
|
||||
if (reasoningEnabled) {
|
||||
settings.reasoning_enabled = reasoningEnabled.checked;
|
||||
}
|
||||
|
||||
if (reasoningEffort) {
|
||||
settings.reasoning_effort = reasoningEffort.value;
|
||||
}
|
||||
|
||||
if (webSearchEnabled) {
|
||||
settings.web_search_enabled = webSearchEnabled.checked;
|
||||
}
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, saveAISettingsButton, 'AI settings saved successfully');
|
||||
});
|
||||
}
|
||||
|
||||
// Character settings save button
|
||||
const saveCharacterSettingsButton = document.getElementById('save-character-settings-button');
|
||||
if (saveCharacterSettingsButton) {
|
||||
saveCharacterSettingsButton.addEventListener('click', () => {
|
||||
const characterInput = document.getElementById('ai-character');
|
||||
const characterInfoInput = document.getElementById('ai-character-info');
|
||||
const characterBreakdown = document.getElementById('ai-character-breakdown');
|
||||
// Goodbye message test button
|
||||
const testGoodbyeButton = document.getElementById('test-goodbye-button');
|
||||
if (testGoodbyeButton) {
|
||||
testGoodbyeButton.addEventListener('click', () => {
|
||||
// Show loading state
|
||||
testGoodbyeButton.disabled = true;
|
||||
testGoodbyeButton.classList.add('btn-loading');
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
character: characterInput ? characterInput.value : initialSettings.character,
|
||||
character_info: characterInfoInput ? characterInfoInput.value : initialSettings.character_info
|
||||
};
|
||||
// Send test request to API
|
||||
API.post(`/dashboard/api/guilds/${guildId}/test-goodbye`)
|
||||
.then(response => {
|
||||
console.log('Test goodbye message response:', response);
|
||||
|
||||
// Add optional settings if they exist
|
||||
if (characterBreakdown) {
|
||||
settings.character_breakdown = characterBreakdown.checked;
|
||||
}
|
||||
// Show success message with formatted message
|
||||
Toast.success('Test goodbye message sent!');
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, saveCharacterSettingsButton, 'Character settings saved successfully');
|
||||
});
|
||||
}
|
||||
// Show formatted message in feedback area
|
||||
const goodbyeFeedback = document.getElementById('goodbye-feedback');
|
||||
if (goodbyeFeedback) {
|
||||
goodbyeFeedback.innerHTML = `
|
||||
<div class="mt-4 p-3 border rounded bg-light">
|
||||
<strong>Test Message:</strong>
|
||||
<p class="mb-0">${response.formatted_message}</p>
|
||||
<small class="text-muted">Sent to channel ID: ${response.channel_id}</small>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error testing goodbye message:', error);
|
||||
|
||||
// System prompt save button
|
||||
const saveSystemPromptButton = document.getElementById('save-system-prompt-button');
|
||||
if (saveSystemPromptButton) {
|
||||
saveSystemPromptButton.addEventListener('click', () => {
|
||||
const systemPromptInput = document.getElementById('ai-system-prompt');
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
system_message: systemPromptInput ? systemPromptInput.value : initialSettings.system_message
|
||||
};
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, saveSystemPromptButton, 'System prompt saved successfully');
|
||||
});
|
||||
}
|
||||
|
||||
// Custom instructions save button
|
||||
const saveCustomInstructionsButton = document.getElementById('save-custom-instructions-button');
|
||||
if (saveCustomInstructionsButton) {
|
||||
saveCustomInstructionsButton.addEventListener('click', () => {
|
||||
const customInstructionsInput = document.getElementById('ai-custom-instructions');
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
custom_instructions: customInstructionsInput ? customInstructionsInput.value : initialSettings.custom_instructions
|
||||
};
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, saveCustomInstructionsButton, 'Custom instructions saved successfully');
|
||||
});
|
||||
}
|
||||
|
||||
// Clear buttons
|
||||
const clearCharacterSettingsButton = document.getElementById('clear-character-settings-button');
|
||||
if (clearCharacterSettingsButton) {
|
||||
clearCharacterSettingsButton.addEventListener('click', () => {
|
||||
const characterInput = document.getElementById('ai-character');
|
||||
const characterInfoInput = document.getElementById('ai-character-info');
|
||||
|
||||
if (characterInput) characterInput.value = '';
|
||||
if (characterInfoInput) characterInfoInput.value = '';
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
character: '',
|
||||
character_info: ''
|
||||
};
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, clearCharacterSettingsButton, 'Character settings cleared');
|
||||
});
|
||||
}
|
||||
|
||||
const clearCustomInstructionsButton = document.getElementById('clear-custom-instructions-button');
|
||||
if (clearCustomInstructionsButton) {
|
||||
clearCustomInstructionsButton.addEventListener('click', () => {
|
||||
const customInstructionsInput = document.getElementById('ai-custom-instructions');
|
||||
|
||||
if (customInstructionsInput) customInstructionsInput.value = '';
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
custom_instructions: ''
|
||||
};
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, clearCustomInstructionsButton, 'Custom instructions cleared');
|
||||
});
|
||||
}
|
||||
|
||||
// Reset buttons
|
||||
const resetAISettingsButton = document.getElementById('reset-ai-settings-button');
|
||||
if (resetAISettingsButton) {
|
||||
resetAISettingsButton.addEventListener('click', () => {
|
||||
const modelSelect = document.getElementById('ai-model-select');
|
||||
const temperatureSlider = document.getElementById('ai-temperature');
|
||||
const temperatureValue = document.getElementById('temperature-value');
|
||||
const maxTokensInput = document.getElementById('ai-max-tokens');
|
||||
|
||||
if (modelSelect) modelSelect.value = 'openai/gpt-3.5-turbo';
|
||||
if (temperatureSlider) temperatureSlider.value = 0.7;
|
||||
if (temperatureValue) temperatureValue.textContent = 0.7;
|
||||
if (maxTokensInput) maxTokensInput.value = 1000;
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
model: 'openai/gpt-3.5-turbo',
|
||||
temperature: 0.7,
|
||||
max_tokens: 1000
|
||||
};
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, resetAISettingsButton, 'AI settings reset to defaults');
|
||||
});
|
||||
}
|
||||
|
||||
const resetSystemPromptButton = document.getElementById('reset-system-prompt-button');
|
||||
if (resetSystemPromptButton) {
|
||||
resetSystemPromptButton.addEventListener('click', () => {
|
||||
const systemPromptInput = document.getElementById('ai-system-prompt');
|
||||
|
||||
if (systemPromptInput) systemPromptInput.value = '';
|
||||
|
||||
// Create settings object
|
||||
const settings = {
|
||||
...initialSettings, // Keep other settings
|
||||
system_message: ''
|
||||
};
|
||||
|
||||
// Save settings
|
||||
saveSettings(settings, resetSystemPromptButton, 'System prompt reset to default');
|
||||
// Show error message
|
||||
if (error.status === 400) {
|
||||
Toast.error('Goodbye channel not configured. Please set a goodbye channel first.');
|
||||
} else {
|
||||
Toast.error('Failed to test goodbye message. Please try again.');
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
// Remove loading state
|
||||
testGoodbyeButton.disabled = false;
|
||||
testGoodbyeButton.classList.remove('btn-loading');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save settings to the API
|
||||
* @param {Object} settings - The settings to save
|
||||
* @param {HTMLElement} button - The button that triggered the save
|
||||
* @param {string} successMessage - The message to show on success
|
||||
*/
|
||||
function saveSettings(settings, button, successMessage) {
|
||||
// Save settings to API
|
||||
API.post('/dashboard/api/settings', { settings }, button)
|
||||
.then(response => {
|
||||
console.log('Settings saved:', response);
|
||||
Toast.success(successMessage);
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error saving settings:', error);
|
||||
Toast.error('Failed to save settings. Please try again.');
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user