feat: Implement custom bot configuration dashboard
This commit introduces a new custom bot configuration dashboard, providing a streamlined interface for managing bot settings. Key changes include: - **UI/UX Enhancements:** - Added new CSS for a modern, responsive dashboard layout, including header, navigation, and form styling. - Implemented a dynamic bot status indicator (online/offline). - Improved form validation and user feedback mechanisms. - **Frontend Logic:** - Refactored `custom-bot.js` to handle loading, saving, and validating bot settings. - Integrated `showFeedback` utility for consistent user notifications. - Updated API calls to use `fetch` for better control and error handling. - **HTML Structure:** - Modified `index.html` to incorporate the new dashboard layout and elements. - **Utility Functions:** - Added `showFeedback` function in `utils.js` for displaying success/error messages. This feature significantly improves the user experience for configuring custom bots.
This commit is contained in:
parent
d09a0897c6
commit
0677b7e168
@ -468,3 +468,148 @@ input[type="radio"] {
|
||||
.text-danger {
|
||||
color: var(--danger-color);
|
||||
}
|
||||
|
||||
/* Custom Bot Configuration Dashboard Styles */
|
||||
|
||||
/* Header for the streamlined dashboard */
|
||||
.header {
|
||||
background-color: var(--card-bg);
|
||||
border-bottom: 1px solid var(--border-color);
|
||||
padding: var(--spacing-4) var(--spacing-6);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 600;
|
||||
color: var(--primary-color);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--spacing-3);
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
background-color: var(--primary-color);
|
||||
color: white;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-weight: 600;
|
||||
font-size: 1.125rem;
|
||||
}
|
||||
|
||||
.user-name {
|
||||
font-weight: 500;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
/* Bot status indicator */
|
||||
.w-4 {
|
||||
width: 1rem;
|
||||
}
|
||||
|
||||
.h-4 {
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.rounded-full {
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.bg-gray-400 {
|
||||
background-color: #9CA3AF;
|
||||
}
|
||||
|
||||
.bg-green-500 {
|
||||
background-color: var(--success-color);
|
||||
}
|
||||
|
||||
.bg-red-500 {
|
||||
background-color: var(--danger-color);
|
||||
}
|
||||
|
||||
.bg-yellow-500 {
|
||||
background-color: var(--warning-color);
|
||||
}
|
||||
|
||||
/* Text colors */
|
||||
.text-red-500 {
|
||||
color: var(--danger-color);
|
||||
}
|
||||
|
||||
.text-green-500 {
|
||||
color: var(--success-color);
|
||||
}
|
||||
|
||||
.text-gray-600 {
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
|
||||
.text-blue-500 {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
.hover\:underline:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* List styles for setup guide */
|
||||
.list-decimal {
|
||||
list-style-type: decimal;
|
||||
}
|
||||
|
||||
.list-disc {
|
||||
list-style-type: disc;
|
||||
}
|
||||
|
||||
.pl-5 {
|
||||
padding-left: 1.25rem;
|
||||
}
|
||||
|
||||
.space-y-4 > * + * {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
/* Responsive design */
|
||||
@media (max-width: 768px) {
|
||||
.header {
|
||||
padding: var(--spacing-3) var(--spacing-4);
|
||||
}
|
||||
|
||||
.header-title {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
gap: var(--spacing-2);
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.content-container {
|
||||
padding: var(--spacing-4) !important;
|
||||
}
|
||||
|
||||
.btn-group {
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Bot Dashboard</title>
|
||||
<title>Custom Bot Configuration Dashboard</title>
|
||||
<!-- Preload fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
@ -12,16 +12,13 @@
|
||||
<link rel="stylesheet" href="css/main.css">
|
||||
<link rel="stylesheet" href="css/components.css">
|
||||
<link rel="stylesheet" href="css/layout.css">
|
||||
<link rel="stylesheet" href="css/theme-settings.css">
|
||||
<link rel="stylesheet" href="css/command-customization.css">
|
||||
<link rel="stylesheet" href="css/cog-management.css">
|
||||
</head>
|
||||
<body>
|
||||
<!-- Auth Section -->
|
||||
<div id="auth-section" class="container">
|
||||
<div class="card mt-6" style="max-width: 500px; margin: 100px auto; text-align: center;">
|
||||
<h1>Discord Bot Dashboard</h1>
|
||||
<p class="mb-4">Manage your Discord bot settings and configurations</p>
|
||||
<h1>Custom Bot Configuration</h1>
|
||||
<p class="mb-4">Set up and manage your personalized Discord bot</p>
|
||||
<button id="login-button" class="btn btn-primary btn-lg">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="mr-2"><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>
|
||||
Login with Discord
|
||||
@ -29,602 +26,161 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Server Selection Section (New) -->
|
||||
<div id="server-select-section" class="container dashboard-section" style="display: none; margin-top: 80px;">
|
||||
<!-- Bot Configuration Section -->
|
||||
<div id="bot-config-section" class="container dashboard-section" style="display: none; margin-top: 80px;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Select a Server</h2>
|
||||
<p class="text-muted">Choose the server you want to manage.</p>
|
||||
</div>
|
||||
<div id="server-list-container" class="server-list-grid p-4">
|
||||
<!-- Server items will be populated by JS -->
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
<h2 class="card-title">Custom Bot Setup</h2>
|
||||
<p class="text-muted">Configure your personalized Discord bot with your own token and settings.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Section (Initially hidden until server selected) -->
|
||||
<!-- Main Dashboard Section -->
|
||||
<div id="dashboard-container" class="dashboard-container" style="display: none;">
|
||||
<!-- Sidebar -->
|
||||
<div id="sidebar" class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<a href="#" class="sidebar-logo">Bot Dashboard</a>
|
||||
</div>
|
||||
<div class="sidebar-nav">
|
||||
<a href="#server-settings" class="nav-item active" data-section="server-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"><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="#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="#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="#cog-management" class="nav-item" data-section="cog-management-section" id="nav-cog-management">
|
||||
<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"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
Cog Management
|
||||
</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>
|
||||
<a href="#theme-settings" class="nav-item" data-section="theme-settings-section" id="nav-theme-settings">
|
||||
<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"><circle cx="12" cy="12" r="3"></circle><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"></path></svg>
|
||||
Theme Settings
|
||||
</a>
|
||||
<a href="#custom-bot" class="nav-item" data-section="custom-bot-section" id="nav-custom-bot">
|
||||
<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="3" y="11" width="18" height="11" rx="2" ry="2"></rect><path d="M7 11V7a5 5 0 0 1 10 0v4"></path></svg>
|
||||
Custom Bot
|
||||
</a>
|
||||
<a href="#command-customization" class="nav-item" data-section="command-customization-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="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path><polyline points="15 3 21 3 21 9"></polyline><line x1="10" y1="14" x2="21" y2="3"></line></svg>
|
||||
Command Customization
|
||||
</a>
|
||||
</div>
|
||||
<div class="sidebar-footer">
|
||||
<button id="logout-button" class="btn btn-danger w-full">
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<h1 class="header-title">Custom Bot Configuration</h1>
|
||||
<div class="user-info">
|
||||
<div id="user-avatar" class="user-avatar">U</div>
|
||||
<span id="username" class="user-name">User</span>
|
||||
<button id="logout-button" class="btn btn-danger ml-4">
|
||||
<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="mr-2"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"></path><polyline points="16 17 21 12 16 7"></polyline><line x1="21" y1="12" x2="9" y2="12"></line></svg>
|
||||
Logout
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="main-content">
|
||||
<!-- Header -->
|
||||
<header class="header">
|
||||
<button id="sidebar-toggle" class="sidebar-toggle">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" y1="12" x2="21" y2="12"></line><line x1="3" y1="6" x2="21" y2="6"></line><line x1="3" y1="18" x2="21" y2="18"></line></svg>
|
||||
</button>
|
||||
<h1 class="header-title">Discord Bot Dashboard</h1>
|
||||
<div class="user-info">
|
||||
<div id="user-avatar" class="user-avatar">U</div>
|
||||
<span id="username" class="user-name">User</span>
|
||||
</div>
|
||||
</header>
|
||||
<!-- Content Container -->
|
||||
<div class="content-container" style="margin-top: 80px; padding: 20px;">
|
||||
|
||||
<!-- Content Container -->
|
||||
<div class="content-container" style="margin-top: 80px;">
|
||||
|
||||
<!-- Server Settings Section -->
|
||||
<div id="server-settings-section" class="dashboard-section">
|
||||
<!-- Bot Status Section -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Manage Server Settings</h2>
|
||||
<p class="text-muted">Settings for the selected server.</p> <!-- Added description -->
|
||||
<h2 class="card-title">Bot Status</h2>
|
||||
<p class="text-muted">Current status of your custom Discord bot</p>
|
||||
</div>
|
||||
<!-- Removed guild-select dropdown -->
|
||||
</div>
|
||||
|
||||
<div id="settings-form"> <!-- Display block by default now, JS will load content -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Prefix Settings</h3>
|
||||
<div class="card-body">
|
||||
<div id="bot-status-indicator" class="flex items-center mb-4">
|
||||
<div id="status-dot" class="w-4 h-4 rounded-full bg-gray-400 mr-2"></div>
|
||||
<span id="status-text">Checking status...</span>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="prefix-input">Command Prefix:</label>
|
||||
<div class="flex gap-2">
|
||||
<input type="text" id="prefix-input" name="prefix" maxlength="10" class="w-full">
|
||||
<button id="save-prefix-button" class="btn btn-primary">
|
||||
Save Prefix
|
||||
</button>
|
||||
</div>
|
||||
<p id="prefix-feedback" class="mt-2"></p>
|
||||
<div id="bot-controls" class="flex gap-2">
|
||||
<button id="start-bot-button" class="btn btn-primary" disabled>Start Bot</button>
|
||||
<button id="stop-bot-button" class="btn btn-danger" disabled>Stop Bot</button>
|
||||
</div>
|
||||
<div id="bot-error" class="mt-4 text-red-500 hidden"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Welcome/Leave Module Section -->
|
||||
<div id="welcome-module-section" class="dashboard-section" style="display: none;">
|
||||
<!-- Bot Configuration Section -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Welcome & Leave Messages</h2>
|
||||
<h2 class="card-title">Bot Configuration</h2>
|
||||
<p class="text-muted">Configure your custom Discord bot settings</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="welcome-settings-form" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Welcome Messages</h3>
|
||||
<div class="card-body">
|
||||
<div class="form-group">
|
||||
<label for="bot-token-input">Bot Token:</label>
|
||||
<input type="password" id="bot-token-input" class="w-full" placeholder="Enter your Discord bot token">
|
||||
<p class="text-sm text-gray-600 mt-1">Your bot token is stored securely and never shared.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="welcome-channel">Welcome Channel:</label>
|
||||
<div class="flex gap-2">
|
||||
<input type="text" id="welcome-channel" name="welcome_channel_id" placeholder="Enter Channel ID" class="w-full">
|
||||
<select id="welcome-channel-select" class="w-full">
|
||||
<option value="">-- Select Channel --</option>
|
||||
<!-- Will be populated by JS -->
|
||||
</select>
|
||||
</div>
|
||||
<label for="bot-prefix-input">Command Prefix:</label>
|
||||
<input type="text" id="bot-prefix-input" class="w-full" placeholder="!" maxlength="5">
|
||||
<p class="text-sm text-gray-600 mt-1">The prefix users will type before commands (e.g., !help).</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="welcome-message">Welcome Message Template:</label>
|
||||
<textarea id="welcome-message" name="welcome_message" rows="4" placeholder="Use {user} for mention, {username} for name, {server} for server name." class="w-full"></textarea>
|
||||
</div>
|
||||
<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>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Goodbye Messages</h3>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="goodbye-channel">Goodbye Channel:</label>
|
||||
<div class="flex gap-2">
|
||||
<input type="text" id="goodbye-channel" name="goodbye_channel_id" placeholder="Enter Channel ID" class="w-full">
|
||||
<select id="goodbye-channel-select" class="w-full">
|
||||
<option value="">-- Select Channel --</option>
|
||||
<!-- Will be populated by JS -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="goodbye-message">Goodbye Message Template:</label>
|
||||
<textarea id="goodbye-message" name="goodbye_message" rows="4" placeholder="Use {username} for name, {server} for server name." class="w-full"></textarea>
|
||||
</div>
|
||||
<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>
|
||||
</div>
|
||||
<div class="cogs-container p-4 border rounded mb-4">
|
||||
<div id="cogs-list">
|
||||
<!-- Cog checkboxes will be populated by JS -->
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="save-cogs-button" class="btn btn-primary">Save Module Settings</button>
|
||||
</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>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="command-select">Command:</label>
|
||||
<select id="command-select" class="w-full">
|
||||
<!-- Will be populated by JS -->
|
||||
<option value="">-- Select Command --</option>
|
||||
<label for="bot-status-type-select">Status Type:</label>
|
||||
<select id="bot-status-type-select" class="w-full">
|
||||
<option value="playing">Playing</option>
|
||||
<option value="listening">Listening to</option>
|
||||
<option value="watching">Watching</option>
|
||||
<option value="competing">Competing in</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="role-select">Role:</label>
|
||||
<select id="role-select" class="w-full">
|
||||
<!-- Will be populated by JS -->
|
||||
<option value="">-- Select Role --</option>
|
||||
</select>
|
||||
<label for="bot-status-text-input">Status Text:</label>
|
||||
<input type="text" id="bot-status-text-input" class="w-full" placeholder="!help" maxlength="128">
|
||||
<p class="text-sm text-gray-600 mt-1">The text that will appear in your bot's status.</p>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button id="add-perm-button" class="btn btn-success">Allow Role</button>
|
||||
<button id="remove-perm-button" class="btn btn-danger">Disallow Role</button>
|
||||
<button id="save-bot-config-button" class="btn btn-primary">Save Configuration</button>
|
||||
</div>
|
||||
<div id="current-perms" class="mt-4 p-4 border rounded">
|
||||
<!-- Current permissions will be listed here -->
|
||||
<div class="text-gray">No permissions set yet.</div>
|
||||
</div>
|
||||
<p id="perms-feedback" class="mt-2"></p>
|
||||
<p id="bot-config-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI Settings Section Removed -->
|
||||
|
||||
<!-- Include Theme Settings Section -->
|
||||
<div id="theme-settings-template" style="display: none;">
|
||||
<!-- This template will be used to restore the form after loading -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Theme Mode</h3>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="radio-group">
|
||||
<input type="radio" id="theme-mode-light" name="theme_mode" value="light" checked>
|
||||
<label for="theme-mode-light">Light Mode</label>
|
||||
</div>
|
||||
<div class="radio-group">
|
||||
<input type="radio" id="theme-mode-dark" name="theme_mode" value="dark">
|
||||
<label for="theme-mode-dark">Dark Mode</label>
|
||||
</div>
|
||||
<div class="radio-group">
|
||||
<input type="radio" id="theme-mode-custom" name="theme_mode" value="custom">
|
||||
<label for="theme-mode-custom">Custom Mode</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="custom-theme-settings" class="card" style="display: none;">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Custom Colors</h3>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="primary-color">Primary Color:</label>
|
||||
<div class="color-picker-container">
|
||||
<input type="color" id="primary-color" value="#5865F2">
|
||||
<input type="text" id="primary-color-text" value="#5865F2" class="color-text-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="secondary-color">Secondary Color:</label>
|
||||
<div class="color-picker-container">
|
||||
<input type="color" id="secondary-color" value="#2D3748">
|
||||
<input type="text" id="secondary-color-text" value="#2D3748" class="color-text-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="accent-color">Accent Color:</label>
|
||||
<div class="color-picker-container">
|
||||
<input type="color" id="accent-color" value="#7289DA">
|
||||
<input type="text" id="accent-color-text" value="#7289DA" class="color-text-input">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="font-family">Font Family:</label>
|
||||
<select id="font-family" class="w-full">
|
||||
<option value="Inter, sans-serif">Inter</option>
|
||||
<option value="'Roboto', sans-serif">Roboto</option>
|
||||
<option value="'Open Sans', sans-serif">Open Sans</option>
|
||||
<option value="'Montserrat', sans-serif">Montserrat</option>
|
||||
<option value="'Poppins', sans-serif">Poppins</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="custom-css">Custom CSS (Advanced):</label>
|
||||
<textarea id="custom-css" rows="6" class="w-full" placeholder="Enter custom CSS here..."></textarea>
|
||||
<small class="text-muted">Custom CSS will be applied to the dashboard. Use with caution.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Theme Preview</h3>
|
||||
</div>
|
||||
<div id="theme-preview" class="theme-preview">
|
||||
<div class="preview-header">
|
||||
<div class="preview-title">Header</div>
|
||||
<div class="preview-button">Button</div>
|
||||
</div>
|
||||
<div class="preview-content">
|
||||
<div class="preview-card">
|
||||
<div class="preview-card-header">Card Title</div>
|
||||
<div class="preview-card-body">
|
||||
<p>This is a preview of how your theme will look.</p>
|
||||
<div class="preview-form-control"></div>
|
||||
<div class="preview-button-primary">Primary Button</div>
|
||||
<div class="preview-button-secondary">Secondary Button</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<div class="btn-group">
|
||||
<button id="save-theme-settings-button" class="btn btn-primary">Save Theme Settings</button>
|
||||
<button id="reset-theme-settings-button" class="btn btn-warning">Reset to Defaults</button>
|
||||
</div>
|
||||
<p id="theme-settings-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
<!-- Bot Setup Guide Section -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">How to Create Your Discord Bot</h2>
|
||||
<p class="text-muted">Follow these steps to set up your custom Discord bot</p>
|
||||
</div>
|
||||
|
||||
<!-- Theme Settings Section -->
|
||||
<div id="theme-settings-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Theme Settings</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="theme-settings-form">
|
||||
<!-- Will be populated by JS -->
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include Cog Management Section -->
|
||||
<!-- Cog Management Section -->
|
||||
<div id="cog-management-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Manage Cogs & Commands</h2>
|
||||
<p class="text-muted">Enable/disable modules and commands for the selected server.</p> <!-- Added description -->
|
||||
</div>
|
||||
<!-- Removed cog-guild-select dropdown -->
|
||||
</div>
|
||||
|
||||
<div id="cog-management-loading" class="loading-container">
|
||||
<div class="loading-spinner"></div>
|
||||
<p>Loading cogs and commands...</p>
|
||||
</div>
|
||||
|
||||
<div id="cog-management-content" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Cogs (Modules)</h3>
|
||||
<p class="text-sm text-muted">Enable or disable entire modules of functionality</p>
|
||||
</div>
|
||||
<div class="cogs-list-container p-4">
|
||||
<div id="cogs-list" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<!-- Cogs will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group mt-4">
|
||||
<button id="save-cogs-button" class="btn btn-primary">Save Cog Settings</button>
|
||||
</div>
|
||||
<p id="cogs-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
|
||||
<div class="card mt-6">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Commands</h3>
|
||||
<p class="text-sm text-muted">Enable or disable individual commands</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="cog-filter">Filter by Cog:</label>
|
||||
<select id="cog-filter" class="w-full">
|
||||
<option value="all">All Cogs</option>
|
||||
<!-- Cog options will be populated here -->
|
||||
</select>
|
||||
</div>
|
||||
<div class="commands-list-container p-4">
|
||||
<div id="commands-list" class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
<!-- Commands will be populated here -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="btn-group mt-4">
|
||||
<button id="save-commands-button" class="btn btn-primary">Save Command Settings</button>
|
||||
</div>
|
||||
<p id="commands-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include Command Customization Section -->
|
||||
<div id="command-customization-section" class="dashboard-section" style="display: none;">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h2 class="card-title">Command Customization</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="command-customization-form">
|
||||
<!-- Command Customization Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Customize Commands</h3>
|
||||
<p class="text-muted">Customize the names and descriptions of commands for your server.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="search-container">
|
||||
<input type="text" id="command-search" placeholder="Search commands..." class="w-full">
|
||||
</div>
|
||||
</div>
|
||||
<div id="command-list" class="command-list">
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Command Group Customization Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Customize Command Groups</h3>
|
||||
<p class="text-muted">Customize the names of command groups for your server.</p>
|
||||
</div>
|
||||
<div id="group-list" class="command-list">
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Command Aliases Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Command Aliases</h3>
|
||||
<p class="text-muted">Add alternative names for commands.</p>
|
||||
</div>
|
||||
<div id="alias-list" class="command-list">
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group mt-4">
|
||||
<h4>Add New Alias</h4>
|
||||
<div class="flex-row">
|
||||
<div class="flex-col mr-2">
|
||||
<label for="alias-command-select">Command:</label>
|
||||
<select id="alias-command-select" class="w-full">
|
||||
<option value="">Select a command</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="flex-col">
|
||||
<label for="alias-name-input">Alias:</label>
|
||||
<input type="text" id="alias-name-input" placeholder="Enter alias name" class="w-full">
|
||||
</div>
|
||||
</div>
|
||||
<button id="add-alias-button" class="btn btn-primary mt-2">Add Alias</button>
|
||||
<p id="alias-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sync Commands Card -->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Sync Commands</h3>
|
||||
<p class="text-muted">Sync command customizations to Discord.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<p>After making changes to command names, descriptions, or aliases, you need to sync the changes to Discord.</p>
|
||||
<button id="sync-commands-button" class="btn btn-primary">Sync Commands</button>
|
||||
<p id="sync-feedback" class="mt-2"></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Include Custom Bot Section -->
|
||||
<div id="custom-bot-section" class="dashboard-section" style="display: none;">
|
||||
<!-- This will be loaded from custom-bot.html -->
|
||||
<div class="loading-spinner-container">
|
||||
<div class="loading-spinner"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Command Customization Templates -->
|
||||
<template id="command-item-template">
|
||||
<div class="command-item">
|
||||
<div class="command-header">
|
||||
<h4 class="command-name"></h4>
|
||||
<div class="command-actions">
|
||||
<button class="btn btn-sm btn-primary edit-command-btn">Edit</button>
|
||||
<button class="btn btn-sm btn-warning reset-command-btn">Reset</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="command-details">
|
||||
<p class="command-description"></p>
|
||||
<div class="command-customization" style="display: none;">
|
||||
<div class="form-group">
|
||||
<label>Custom Name:</label>
|
||||
<input type="text" class="custom-command-name w-full" placeholder="Enter custom name">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Custom Description:</label>
|
||||
<input type="text" class="custom-command-description w-full" placeholder="Enter custom description">
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-primary save-command-btn">Save</button>
|
||||
<button class="btn btn-sm btn-secondary cancel-command-btn">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="group-item-template">
|
||||
<div class="command-item">
|
||||
<div class="command-header">
|
||||
<h4 class="group-name"></h4>
|
||||
<div class="command-actions">
|
||||
<button class="btn btn-sm btn-primary edit-group-btn">Edit</button>
|
||||
<button class="btn btn-sm btn-warning reset-group-btn">Reset</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="group-details">
|
||||
<div class="group-customization" style="display: none;">
|
||||
<div class="form-group">
|
||||
<label>Custom Name:</label>
|
||||
<input type="text" class="custom-group-name w-full" placeholder="Enter custom name">
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm btn-primary save-group-btn">Save</button>
|
||||
<button class="btn btn-sm btn-secondary cancel-group-btn">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="alias-item-template">
|
||||
<div class="alias-item">
|
||||
<div class="alias-header">
|
||||
<h4 class="command-name"></h4>
|
||||
</div>
|
||||
<div class="alias-list">
|
||||
<ul class="alias-tags">
|
||||
<!-- Alias tags will be added here -->
|
||||
<div class="card-body">
|
||||
<ol class="list-decimal pl-5 space-y-4">
|
||||
<li>
|
||||
<strong>Create a Discord Application:</strong>
|
||||
<p>Go to the <a href="https://discord.com/developers/applications" target="_blank" class="text-blue-500 hover:underline">Discord Developer Portal</a> and click "New Application".</p>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Set Up Your Bot:</strong>
|
||||
<p>In your application, go to the "Bot" tab and click "Add Bot".</p>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Customize Your Bot:</strong>
|
||||
<p>Upload a profile picture and set a username for your bot.</p>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Get Your Bot Token:</strong>
|
||||
<p>Click "Reset Token" to generate a new token, then copy it.</p>
|
||||
<p class="text-red-500">IMPORTANT: Never share your bot token with anyone!</p>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Set Bot Permissions:</strong>
|
||||
<p>In the "Bot" tab, under "Privileged Gateway Intents", enable:</p>
|
||||
<ul class="list-disc pl-5">
|
||||
<li>Presence Intent</li>
|
||||
<li>Server Members Intent</li>
|
||||
<li>Message Content Intent</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template id="alias-tag-template">
|
||||
<li class="alias-tag">
|
||||
<span class="alias-name"></span>
|
||||
<button class="remove-alias-btn">×</button>
|
||||
</li>
|
||||
</template>
|
||||
|
||||
</li>
|
||||
<li>
|
||||
<strong>Invite Your Bot:</strong>
|
||||
<p>Go to the "OAuth2" tab, then "URL Generator". Select the following scopes:</p>
|
||||
<ul class="list-disc pl-5">
|
||||
<li>bot</li>
|
||||
<li>applications.commands</li>
|
||||
</ul>
|
||||
<p>Then select the following bot permissions:</p>
|
||||
<ul class="list-disc pl-5">
|
||||
<li>Send Messages</li>
|
||||
<li>Embed Links</li>
|
||||
<li>Attach Files</li>
|
||||
<li>Read Message History</li>
|
||||
<li>Use Slash Commands</li>
|
||||
<li>Add Reactions</li>
|
||||
</ul>
|
||||
<p>Copy the generated URL and open it in your browser to invite the bot to your server.</p>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Configure Your Bot:</strong>
|
||||
<p>Paste your bot token in the configuration form above and save it.</p>
|
||||
</li>
|
||||
<li>
|
||||
<strong>Start Your Bot:</strong>
|
||||
<p>Click the "Start Bot" button to bring your bot online!</p>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- JavaScript files -->
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/main.js"></script>
|
||||
<!-- <script src="js/ai-settings.js"></script> --> <!-- Removed AI settings script -->
|
||||
<script src="js/theme-settings.js"></script>
|
||||
<script src="js/custom-bot.js"></script>
|
||||
<script src="js/command-customization.js"></script>
|
||||
<script src="js/cog-management.js"></script>
|
||||
<!-- JavaScript files -->
|
||||
<script src="js/utils.js"></script>
|
||||
<script src="js/custom-bot.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Custom Bot Management
|
||||
* This module handles the custom bot functionality in the dashboard.
|
||||
* Custom Bot Configuration Dashboard
|
||||
* Streamlined interface for bot setup and management
|
||||
*/
|
||||
|
||||
// Status constants
|
||||
@ -22,11 +22,14 @@ let stopBotButton;
|
||||
let statusDot;
|
||||
let statusText;
|
||||
let botError;
|
||||
let botConfigFeedback;
|
||||
|
||||
/**
|
||||
* Initialize the custom bot functionality
|
||||
*/
|
||||
function initCustomBot() {
|
||||
console.log('Initializing custom bot dashboard...');
|
||||
|
||||
// Get DOM elements
|
||||
botTokenInput = document.getElementById('bot-token-input');
|
||||
botPrefixInput = document.getElementById('bot-prefix-input');
|
||||
@ -38,6 +41,7 @@ function initCustomBot() {
|
||||
statusDot = document.getElementById('status-dot');
|
||||
statusText = document.getElementById('status-text');
|
||||
botError = document.getElementById('bot-error');
|
||||
botConfigFeedback = document.getElementById('bot-config-feedback');
|
||||
|
||||
// Add event listeners
|
||||
if (saveBotConfigButton) {
|
||||
@ -65,27 +69,43 @@ function initCustomBot() {
|
||||
*/
|
||||
async function loadCustomBotSettings() {
|
||||
try {
|
||||
const response = await API.get('/dashboard/api/settings');
|
||||
console.log('Loading custom bot settings...');
|
||||
const response = await fetch('/dashboard/api/settings', {
|
||||
method: 'GET',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
console.log('Loaded bot settings:', data);
|
||||
|
||||
// Fill in the form fields
|
||||
if (botTokenInput && response.custom_bot_token) {
|
||||
botTokenInput.value = response.custom_bot_token;
|
||||
if (botTokenInput && data.custom_bot_token) {
|
||||
botTokenInput.value = data.custom_bot_token;
|
||||
}
|
||||
|
||||
if (botPrefixInput) {
|
||||
botPrefixInput.value = response.custom_bot_prefix || '!';
|
||||
botPrefixInput.value = data.custom_bot_prefix || '!';
|
||||
}
|
||||
|
||||
if (botStatusTypeSelect) {
|
||||
botStatusTypeSelect.value = response.custom_bot_status_type || 'listening';
|
||||
botStatusTypeSelect.value = data.custom_bot_status_type || 'listening';
|
||||
}
|
||||
|
||||
if (botStatusTextInput) {
|
||||
botStatusTextInput.value = response.custom_bot_status_text || '!help';
|
||||
botStatusTextInput.value = data.custom_bot_status_text || '!help';
|
||||
}
|
||||
|
||||
showFeedback('Bot settings loaded successfully', false);
|
||||
} catch (error) {
|
||||
console.error('Error loading custom bot settings:', error);
|
||||
Toast.error('Failed to load custom bot settings');
|
||||
showFeedback('Failed to load custom bot settings: ' + error.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -94,44 +114,58 @@ async function loadCustomBotSettings() {
|
||||
*/
|
||||
async function saveCustomBotConfig() {
|
||||
try {
|
||||
console.log('Saving custom bot configuration...');
|
||||
|
||||
// Validate inputs
|
||||
if (!botTokenInput.value) {
|
||||
Toast.error('Bot token is required');
|
||||
if (!botTokenInput.value.trim()) {
|
||||
showFeedback('Bot token is required', true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!botPrefixInput.value) {
|
||||
Toast.error('Command prefix is required');
|
||||
if (!botPrefixInput.value.trim()) {
|
||||
showFeedback('Command prefix is required', true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!botStatusTextInput.value) {
|
||||
Toast.error('Status text is required');
|
||||
if (!botStatusTextInput.value.trim()) {
|
||||
showFeedback('Status text is required', true);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get current settings first
|
||||
const currentSettings = await API.get('/dashboard/api/settings');
|
||||
|
||||
// Prepare the settings object with updated bot settings
|
||||
// Prepare the settings object
|
||||
const settings = {
|
||||
...currentSettings,
|
||||
custom_bot_token: botTokenInput.value,
|
||||
custom_bot_prefix: botPrefixInput.value,
|
||||
custom_bot_token: botTokenInput.value.trim(),
|
||||
custom_bot_prefix: botPrefixInput.value.trim(),
|
||||
custom_bot_status_type: botStatusTypeSelect.value,
|
||||
custom_bot_status_text: botStatusTextInput.value
|
||||
custom_bot_status_text: botStatusTextInput.value.trim()
|
||||
};
|
||||
|
||||
// Save the settings
|
||||
await API.put('/dashboard/api/settings', settings);
|
||||
console.log('Sending bot configuration:', settings);
|
||||
|
||||
Toast.success('Custom bot configuration saved successfully');
|
||||
// Save the settings
|
||||
const response = await fetch('/dashboard/api/settings', {
|
||||
method: 'PUT',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(settings)
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log('Bot configuration saved:', result);
|
||||
|
||||
showFeedback('Custom bot configuration saved successfully', false);
|
||||
|
||||
// Check bot status after saving
|
||||
checkBotStatus();
|
||||
setTimeout(checkBotStatus, 1000);
|
||||
} catch (error) {
|
||||
console.error('Error saving custom bot configuration:', error);
|
||||
Toast.error('Failed to save custom bot configuration');
|
||||
showFeedback('Failed to save custom bot configuration: ' + error.message, true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -140,18 +174,32 @@ async function saveCustomBotConfig() {
|
||||
*/
|
||||
async function startCustomBot() {
|
||||
try {
|
||||
console.log('Starting custom bot...');
|
||||
startBotButton.disabled = true;
|
||||
startBotButton.textContent = 'Starting...';
|
||||
|
||||
await API.post('/dashboard/api/custom-bot/start');
|
||||
const response = await fetch('/dashboard/api/custom-bot/start', {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
Toast.success('Custom bot started successfully');
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log('Bot start result:', result);
|
||||
|
||||
showFeedback('Custom bot started successfully', false);
|
||||
|
||||
// Check bot status after starting
|
||||
checkBotStatus();
|
||||
setTimeout(checkBotStatus, 2000);
|
||||
} catch (error) {
|
||||
console.error('Error starting custom bot:', error);
|
||||
Toast.error('Failed to start custom bot: ' + (error.response?.data?.detail || error.message));
|
||||
showFeedback('Failed to start custom bot: ' + error.message, true);
|
||||
|
||||
// Re-enable the button
|
||||
startBotButton.disabled = false;
|
||||
@ -164,18 +212,32 @@ async function startCustomBot() {
|
||||
*/
|
||||
async function stopCustomBot() {
|
||||
try {
|
||||
console.log('Stopping custom bot...');
|
||||
stopBotButton.disabled = true;
|
||||
stopBotButton.textContent = 'Stopping...';
|
||||
|
||||
await API.post('/dashboard/api/custom-bot/stop');
|
||||
const response = await fetch('/dashboard/api/custom-bot/stop', {
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
Toast.success('Custom bot stopped successfully');
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
console.log('Bot stop result:', result);
|
||||
|
||||
showFeedback('Custom bot stopped successfully', false);
|
||||
|
||||
// Check bot status after stopping
|
||||
checkBotStatus();
|
||||
setTimeout(checkBotStatus, 2000);
|
||||
} catch (error) {
|
||||
console.error('Error stopping custom bot:', error);
|
||||
Toast.error('Failed to stop custom bot: ' + (error.response?.data?.detail || error.message));
|
||||
showFeedback('Failed to stop custom bot: ' + error.message, true);
|
||||
|
||||
// Re-enable the button
|
||||
stopBotButton.disabled = false;
|
||||
@ -188,17 +250,30 @@ async function stopCustomBot() {
|
||||
*/
|
||||
async function checkBotStatus() {
|
||||
try {
|
||||
const response = await API.get('/dashboard/api/custom-bot/status');
|
||||
const response = await fetch('/dashboard/api/custom-bot/status', {
|
||||
method: 'GET',
|
||||
credentials: 'include',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
|
||||
const status = await response.json();
|
||||
console.log('Bot status:', status);
|
||||
|
||||
// Update the status indicator
|
||||
updateStatusIndicator(response);
|
||||
updateStatusIndicator(status);
|
||||
|
||||
// Update button states
|
||||
updateButtonStates(response);
|
||||
updateButtonStates(status);
|
||||
|
||||
// Show error if any
|
||||
if (response.error && botError) {
|
||||
botError.textContent = response.error;
|
||||
if (status.error && botError) {
|
||||
botError.textContent = status.error;
|
||||
botError.classList.remove('hidden');
|
||||
} else if (botError) {
|
||||
botError.classList.add('hidden');
|
||||
@ -271,5 +346,29 @@ function updateButtonStates(status) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show feedback message to user
|
||||
*/
|
||||
function showFeedback(message, isError = false) {
|
||||
if (botConfigFeedback) {
|
||||
botConfigFeedback.textContent = message;
|
||||
botConfigFeedback.className = isError ? 'mt-2 text-red-500' : 'mt-2 text-green-500';
|
||||
|
||||
// Clear feedback after 5 seconds
|
||||
setTimeout(() => {
|
||||
if (botConfigFeedback) {
|
||||
botConfigFeedback.textContent = '';
|
||||
botConfigFeedback.className = 'mt-2';
|
||||
}
|
||||
}, 5000);
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM loaded, initializing custom bot dashboard...');
|
||||
initCustomBot();
|
||||
});
|
||||
|
||||
// Export the initialization function
|
||||
window.initCustomBot = initCustomBot;
|
||||
|
@ -661,9 +661,111 @@ const DOM = {
|
||||
}
|
||||
};
|
||||
|
||||
// Authentication utilities
|
||||
const Auth = {
|
||||
async checkAuth() {
|
||||
try {
|
||||
const response = await fetch('/dashboard/api/user', {
|
||||
method: 'GET',
|
||||
credentials: 'include'
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
const user = await response.json();
|
||||
console.log('User authenticated:', user);
|
||||
return user;
|
||||
} else {
|
||||
console.log('User not authenticated');
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Auth check failed:', error);
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
redirectToLogin() {
|
||||
window.location.href = '/dashboard/api/auth/discord';
|
||||
},
|
||||
|
||||
async logout() {
|
||||
try {
|
||||
await fetch('/dashboard/api/auth/logout', {
|
||||
method: 'POST',
|
||||
credentials: 'include'
|
||||
});
|
||||
window.location.reload();
|
||||
} catch (error) {
|
||||
console.error('Logout failed:', error);
|
||||
window.location.reload();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Main dashboard initialization
|
||||
async function initDashboard() {
|
||||
console.log('Initializing dashboard...');
|
||||
|
||||
const authSection = document.getElementById('auth-section');
|
||||
const botConfigSection = document.getElementById('bot-config-section');
|
||||
const dashboardContainer = document.getElementById('dashboard-container');
|
||||
const loginButton = document.getElementById('login-button');
|
||||
const logoutButton = document.getElementById('logout-button');
|
||||
const usernameSpan = document.getElementById('username');
|
||||
const userAvatar = document.getElementById('user-avatar');
|
||||
|
||||
// Check authentication
|
||||
const user = await Auth.checkAuth();
|
||||
|
||||
if (user) {
|
||||
// User is authenticated, show dashboard
|
||||
console.log('User authenticated, showing dashboard');
|
||||
DOM.hide(authSection);
|
||||
DOM.hide(botConfigSection);
|
||||
DOM.show(dashboardContainer);
|
||||
|
||||
// Update user info
|
||||
if (usernameSpan) {
|
||||
usernameSpan.textContent = user.username || 'User';
|
||||
}
|
||||
if (userAvatar) {
|
||||
userAvatar.textContent = (user.username || 'U').charAt(0).toUpperCase();
|
||||
}
|
||||
} else {
|
||||
// User not authenticated, show login
|
||||
console.log('User not authenticated, showing login');
|
||||
DOM.show(authSection);
|
||||
DOM.hide(botConfigSection);
|
||||
DOM.hide(dashboardContainer);
|
||||
}
|
||||
|
||||
// Add event listeners
|
||||
if (loginButton) {
|
||||
loginButton.addEventListener('click', () => {
|
||||
console.log('Login button clicked');
|
||||
Auth.redirectToLogin();
|
||||
});
|
||||
}
|
||||
|
||||
if (logoutButton) {
|
||||
logoutButton.addEventListener('click', () => {
|
||||
console.log('Logout button clicked');
|
||||
Auth.logout();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize when DOM is loaded
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('DOM loaded, initializing dashboard...');
|
||||
initDashboard();
|
||||
});
|
||||
|
||||
// Export utilities
|
||||
window.Toast = Toast;
|
||||
window.API = API;
|
||||
window.Modal = Modal;
|
||||
window.Form = Form;
|
||||
window.DOM = DOM;
|
||||
window.Auth = Auth;
|
||||
window.initDashboard = initDashboard;
|
||||
|
Loading…
x
Reference in New Issue
Block a user