refactor: standardize raw fetch() calls to use apiCall() wrapper

Convert 47 raw fetch+response.json+error-handling patterns to use the
centralized apiCall() utility. The 11 remaining raw fetch() calls are
FormData uploads or SSE streaming that require direct fetch access.
This commit is contained in:
2026-03-01 00:14:08 +02:00
parent 820a226dd9
commit 5bdd907730

View File

@@ -2023,8 +2023,7 @@ async function apiCall(endpoint, method = 'GET', data = null) {
async function loadServers() {
try {
console.log('🎭 Loading servers...');
const response = await fetch('/servers');
const data = await response.json();
const data = await apiCall('/servers');
console.log('🎭 Servers response:', data);
if (data.servers) {
@@ -2124,10 +2123,9 @@ function displayServers() {
async function loadProfilePictureMetadata() {
try {
const response = await fetch('/profile-picture/metadata');
const result = await response.json();
const result = await apiCall('/profile-picture/metadata');
if (response.ok && result.status === 'ok' && result.metadata) {
if (result.status === 'ok' && result.metadata) {
const metadataDiv = document.getElementById('pfp-metadata');
const metadataContent = document.getElementById('pfp-metadata-content');
@@ -2182,14 +2180,12 @@ async function populateServerDropdowns() {
async function refreshFigurineSubscribers() {
try {
console.log('🔄 Figurines: Fetching subscribers...');
const res = await fetch('/figurines/subscribers');
const data = await res.json();
const data = await apiCall('/figurines/subscribers');
console.log('📋 Figurines: Received subscribers:', data);
displayFigurineSubscribers(data.subscribers || []);
showNotification('Subscribers refreshed');
} catch (e) {
console.error('❌ Figurines: Failed to fetch subscribers:', e);
showNotification('Failed to load subscribers', 'error');
}
}
@@ -2238,8 +2234,7 @@ async function addFigurineSubscriber() {
async function removeFigurineSubscriber(uid) {
try {
console.log(`🗑️ Figurines: Removing subscriber ${uid}...`);
const res = await fetch(`/figurines/subscribers/${uid}`, { method: 'DELETE' });
const data = await res.json();
const data = await apiCall(`/figurines/subscribers/${uid}`, 'DELETE');
console.log('🗑️ Figurines: Remove subscriber response:', data);
if (data.status === 'ok') {
showNotification('Subscriber removed');
@@ -2249,7 +2244,6 @@ async function removeFigurineSubscriber(uid) {
}
} catch (e) {
console.error('❌ Figurines: Failed to remove subscriber:', e);
showNotification('Failed to remove subscriber', 'error');
}
}
@@ -2425,8 +2419,7 @@ async function repairConfig() {
async function populateMoodDropdowns() {
try {
console.log('🎭 Loading available moods...');
const response = await fetch('/moods/available');
const data = await response.json();
const data = await apiCall('/moods/available');
console.log('🎭 Available moods response:', data);
if (data.moods) {
@@ -2597,25 +2590,13 @@ async function updateBedtimeRange(guildId) {
}
// Send the update request
const response = await fetch(`/servers/${guildIdStr}/bedtime-range`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
await apiCall(`/servers/${guildIdStr}/bedtime-range`, 'POST', {
bedtime_hour: startHour,
bedtime_minute: startMinute,
bedtime_hour_end: endHour,
bedtime_minute_end: endMinute
})
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({}));
throw new Error(errorData.message || `HTTP ${response.status}`);
}
const result = await response.json();
showNotification(`Bedtime range updated: ${startTime} - ${endTime}`);
// Reload servers to show updated configuration
@@ -2623,7 +2604,6 @@ async function updateBedtimeRange(guildId) {
} catch (error) {
console.error('Failed to update bedtime range:', error);
showNotification(error.message || 'Failed to update bedtime range', 'error');
} finally {
// Restore button state
if (button) {
@@ -2815,12 +2795,9 @@ let selectedGPU = 'nvidia'; // 'nvidia' or 'amd'
async function checkGPUStatus() {
try {
const response = await fetch('/gpu-status');
if (response.ok) {
const data = await response.json();
const data = await apiCall('/gpu-status');
selectedGPU = data.gpu || 'nvidia';
updateGPUUI();
}
} catch (error) {
console.error('Failed to check GPU status:', error);
}
@@ -2868,12 +2845,9 @@ let bipolarMode = false;
async function checkBipolarModeStatus() {
try {
const response = await fetch('/bipolar-mode');
if (response.ok) {
const data = await response.json();
const data = await apiCall('/bipolar-mode');
bipolarMode = data.bipolar_mode;
updateBipolarModeUI();
}
} catch (error) {
console.error('Failed to check bipolar mode status:', error);
}
@@ -3106,10 +3080,7 @@ async function loadScoreboard() {
async function loadActiveArguments() {
try {
const response = await fetch('/bipolar-mode/arguments');
if (!response.ok) return;
const data = await response.json();
const data = await apiCall('/bipolar-mode/arguments');
const container = document.getElementById('active-arguments');
const list = document.getElementById('active-arguments-list');
@@ -3155,21 +3126,10 @@ async function triggerAutonomous(actionType) {
endpoint += `?guild_id=${selectedServer}`;
}
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (response.ok) {
const result = await apiCall(endpoint, 'POST');
showNotification(result.message || 'Action triggered successfully');
} else {
throw new Error(result.message || 'Failed to trigger action');
}
} catch (error) {
console.error('Failed to trigger autonomous action:', error);
showNotification(error.message || 'Failed to trigger action', 'error');
}
}
@@ -3215,23 +3175,12 @@ async function triggerEngageUser() {
endpoint += `?${params.toString()}`;
}
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (response.ok) {
const result = await apiCall(endpoint, 'POST');
showNotification(result.message || 'Engagement triggered successfully');
// Optionally collapse the submenu after successful trigger
// toggleEngageSubmenu();
} else {
throw new Error(result.message || 'Failed to trigger engagement');
}
} catch (error) {
console.error('Failed to trigger user engagement:', error);
showNotification(error.message || 'Failed to trigger engagement', 'error');
}
}
@@ -3287,21 +3236,10 @@ async function triggerShareTweet() {
endpoint += `?${params.toString()}`;
}
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (response.ok) {
const result = await apiCall(endpoint, 'POST');
showNotification(result.message || 'Tweet share triggered successfully');
} else {
throw new Error(result.message || 'Failed to trigger tweet share');
}
} catch (error) {
console.error('Failed to trigger tweet share:', error);
showNotification(error.message || 'Failed to trigger tweet share', 'error');
}
}
@@ -3326,13 +3264,8 @@ async function changeProfilePicture() {
const url = params.toString() ? `${endpoint}?${params.toString()}` : endpoint;
const response = await fetch(url, {
method: 'POST'
});
const result = await apiCall(url, 'POST');
const result = await response.json();
if (response.ok && result.status === 'ok') {
statusDiv.textContent = `${result.message}`;
statusDiv.style.color = 'green';
@@ -3343,14 +3276,10 @@ async function changeProfilePicture() {
}
showNotification('Profile picture changed successfully!');
} else {
throw new Error(result.message || 'Failed to change profile picture');
}
} catch (error) {
console.error('Failed to change profile picture:', error);
statusDiv.textContent = `❌ Error: ${error.message}`;
statusDiv.style.color = 'red';
showNotification(error.message || 'Failed to change profile picture', 'error');
}
}
@@ -3431,26 +3360,17 @@ async function restoreFallbackPfp() {
statusDiv.style.color = '#61dafb';
try {
const response = await fetch('/profile-picture/restore-fallback', {
method: 'POST'
});
const result = await apiCall('/profile-picture/restore-fallback', 'POST');
const result = await response.json();
if (response.ok && result.status === 'ok') {
statusDiv.textContent = `${result.message}`;
statusDiv.style.color = 'green';
metadataDiv.style.display = 'none';
showNotification('Original avatar restored successfully!');
} else {
throw new Error(result.message || 'Failed to restore fallback avatar');
}
} catch (error) {
console.error('Failed to restore fallback avatar:', error);
statusDiv.textContent = `❌ Error: ${error.message}`;
statusDiv.style.color = 'red';
showNotification(error.message || 'Failed to restore fallback avatar', 'error');
}
}
@@ -3502,13 +3422,8 @@ async function resetRoleColor() {
statusDiv.style.color = '#61dafb';
try {
const response = await fetch('/role-color/reset-fallback', {
method: 'POST'
});
const result = await apiCall('/role-color/reset-fallback', 'POST');
const result = await response.json();
if (response.ok && result.status === 'ok') {
statusDiv.textContent = `${result.message}`;
statusDiv.style.color = 'green';
@@ -3516,14 +3431,10 @@ async function resetRoleColor() {
document.getElementById('role-color-hex').value = '#86cecb';
showNotification('Role color reset to fallback #86cecb');
} else {
throw new Error(result.message || 'Failed to reset role color');
}
} catch (error) {
console.error('Failed to reset role color:', error);
statusDiv.textContent = `❌ Error: ${error.message}`;
statusDiv.style.color = 'red';
showNotification(error.message || 'Failed to reset role color', 'error');
}
}
@@ -3588,7 +3499,7 @@ async function sendCustomPrompt() {
}
try {
let endpoint, requestData, response;
let endpoint;
if (targetType === 'dm') {
// DM target
@@ -3597,16 +3508,7 @@ async function sendCustomPrompt() {
showNotification('Please enter a user ID for DM', 'error');
return;
}
endpoint = `/dm/${userId}/custom`;
requestData = { prompt: prompt };
response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestData)
});
} else {
// Server target
const selectedServer = document.getElementById('custom-prompt-server-select').value;
@@ -3617,19 +3519,10 @@ async function sendCustomPrompt() {
// Don't use parseInt() - Discord IDs are too large for JS integers
endpoint += `?guild_id=${selectedServer}`;
}
requestData = { prompt: prompt };
response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(requestData)
});
}
const result = await response.json();
const result = await apiCall(endpoint, 'POST', { prompt: prompt });
if (response.ok) {
showNotification(result.message || 'Custom prompt sent successfully');
document.getElementById('customPrompt').value = '';
document.getElementById('customPromptAttachment').value = ''; // Clear file input
@@ -3638,12 +3531,8 @@ async function sendCustomPrompt() {
}
document.getElementById('customStatus').textContent = '✅ Custom prompt sent successfully!';
document.getElementById('customStatus').style.color = 'green';
} else {
throw new Error(result.message || 'Failed to send custom prompt');
}
} catch (error) {
console.error('Failed to send custom prompt:', error);
showNotification(error.message || 'Failed to send custom prompt', 'error');
document.getElementById('customStatus').textContent = '❌ Failed to send custom prompt';
document.getElementById('customStatus').style.color = 'red';
}
@@ -3689,21 +3578,10 @@ async function sendBedtime() {
console.log('🛏️ Final endpoint:', endpoint);
const response = await fetch(endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' }
});
const result = await response.json();
if (response.ok) {
const result = await apiCall(endpoint, 'POST');
showNotification(result.message || 'Bedtime reminder sent successfully');
} else {
throw new Error(result.message || 'Failed to send bedtime reminder');
}
} catch (error) {
console.error('Failed to send bedtime reminder:', error);
showNotification(error.message || 'Failed to send bedtime reminder', 'error');
}
}
@@ -3892,10 +3770,8 @@ async function checkImageSystemStatus() {
const statusDisplay = document.getElementById('image-status-display');
statusDisplay.innerHTML = '🔄 Checking system status...';
const response = await fetch('/image/status');
const result = await response.json();
const result = await apiCall('/image/status');
if (response.ok) {
const workflowStatus = result.workflow_template_exists ? '✅ Found' : '❌ Missing';
const comfyuiStatus = result.comfyui_running ? '✅ Running' : '❌ Not running';
@@ -3908,9 +3784,6 @@ ${result.comfyui_running ? `• Detected ComfyUI URL: ${result.comfyui_url}` : '
<strong>Overall Status:</strong> ${result.ready ? '✅ Ready for image generation' : '⚠️ Setup required'}
${!result.workflow_template_exists ? '⚠️ Place Miku_BasicWorkflow.json in bot directory\n' : ''}${!result.comfyui_running ? '⚠️ Start ComfyUI server on localhost:8188 (bot will auto-detect correct URL)\n' : ''}`;
} else {
statusDisplay.innerHTML = `❌ Error checking status: ${result.message}`;
}
} catch (error) {
console.error('Failed to check image system status:', error);
document.getElementById('image-status-display').innerHTML = `❌ Error: ${error.message}`;
@@ -3931,15 +3804,8 @@ async function testImageDetection() {
resultsDiv.innerHTML = '🔍 Testing detection...';
resultsDiv.style.color = '#4CAF50';
const response = await fetch('/image/test-detection', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ message: message })
});
const result = await apiCall('/image/test-detection', 'POST', { message: message });
const result = await response.json();
if (response.ok) {
const detectionIcon = result.is_image_request ? '✅' : '❌';
const detectionText = result.is_image_request ? 'WILL trigger image generation' : 'will NOT trigger image generation';
@@ -3949,10 +3815,6 @@ ${result.is_image_request ? `<br><strong>Extracted Prompt:</strong> "${result.ex
<br><strong>Original Message:</strong> "${result.original_message}"`;
resultsDiv.style.color = result.is_image_request ? '#4CAF50' : '#ff9800';
} else {
resultsDiv.innerHTML = `❌ Detection test failed: ${result.message}`;
resultsDiv.style.color = 'red';
}
} catch (error) {
console.error('Failed to test image detection:', error);
resultsDiv.innerHTML = `❌ Error: ${error.message}`;
@@ -3978,15 +3840,8 @@ async function generateManualImage() {
statusDiv.innerHTML = '🎨 Generating image... This may take a few minutes.';
statusDiv.style.color = '#4CAF50';
const response = await fetch('/image/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt: prompt })
});
const result = await apiCall('/image/generate', 'POST', { prompt: prompt });
const result = await response.json();
if (response.ok && result.status === 'ok') {
statusDiv.innerHTML = `✅ Image generated successfully!`;
statusDiv.style.color = '#4CAF50';
@@ -4030,10 +3885,6 @@ async function generateManualImage() {
}
document.getElementById('manual-image-prompt').value = '';
} else {
statusDiv.innerHTML = `❌ Failed to generate image: ${result.message || 'Unknown error'}`;
statusDiv.style.color = 'red';
}
} catch (error) {
console.error('Failed to generate image:', error);
statusDiv.innerHTML = `❌ Error: ${error.message}`;
@@ -4175,17 +4026,10 @@ function toggleCustomPrompt() {
// DM Logs Functions
async function loadDMUsers() {
try {
const response = await fetch('/dms/users');
const result = await response.json();
if (response.ok) {
const result = await apiCall('/dms/users');
displayDMUsers(result.users);
} else {
throw new Error(result.message || 'Failed to load DM users');
}
} catch (error) {
console.error('Failed to load DM users:', error);
showNotification(error.message || 'Failed to load DM users', 'error');
}
}
@@ -4306,13 +4150,11 @@ function toggleCustomPrompt() {
console.log(`🔍 Original userId: ${userId} (type: ${typeof userId})`);
console.log(`🔍 userIdStr: ${userIdStr} (type: ${typeof userIdStr})`);
const response = await fetch(`/dms/users/${userIdStr}/conversations?limit=100`);
const result = await response.json();
const result = await apiCall(`/dms/users/${userIdStr}/conversations?limit=100`);
console.log('📡 API Response:', result);
console.log('📡 API URL called:', `/dms/users/${userIdStr}/conversations?limit=100`);
if (response.ok) {
if (result.conversations && result.conversations.length > 0) {
console.log(`✅ Found ${result.conversations.length} conversations`);
displayUserConversations(userIdStr, result.conversations);
@@ -4322,12 +4164,8 @@ function toggleCustomPrompt() {
// Go back to user list
loadDMUsers();
}
} else {
throw new Error(result.message || 'Failed to load conversations');
}
} catch (error) {
console.error('Failed to load user conversations:', error);
showNotification(error.message || 'Failed to load conversations', 'error');
}
}
@@ -4419,18 +4257,11 @@ function toggleCustomPrompt() {
try {
// Ensure userId is always treated as a string
const userIdStr = String(userId);
const response = await fetch(`/dms/users/${userIdStr}/export?format=txt`);
const result = await response.json();
if (response.ok) {
await apiCall(`/dms/users/${userIdStr}/export?format=txt`);
showNotification(`DM export completed for user ${userIdStr}`);
// You could trigger a download here if the file is accessible
} else {
throw new Error(result.message || 'Failed to export DMs');
}
} catch (error) {
console.error('Failed to export user DMs:', error);
showNotification(error.message || 'Failed to export DMs', 'error');
}
}
@@ -4443,18 +4274,11 @@ function toggleCustomPrompt() {
}
try {
const response = await fetch(`/dms/users/${userIdStr}`, { method: 'DELETE' });
const result = await response.json();
if (response.ok) {
await apiCall(`/dms/users/${userIdStr}`, 'DELETE');
showNotification(`Deleted DM logs for user ${userIdStr}`);
loadDMUsers(); // Refresh the list
} else {
throw new Error(result.message || 'Failed to delete DM logs');
}
} catch (error) {
console.error('Failed to delete user DMs:', error);
showNotification(error.message || 'Failed to delete DM logs', 'error');
}
}
@@ -4468,18 +4292,11 @@ function toggleCustomPrompt() {
}
try {
const response = await fetch(`/dms/users/${userIdStr}/block`, { method: 'POST' });
const result = await response.json();
if (response.ok) {
await apiCall(`/dms/users/${userIdStr}/block`, 'POST');
showNotification(`${username} has been blocked from sending DMs`);
loadDMUsers(); // Refresh the list
} else {
throw new Error(result.message || 'Failed to block user');
}
} catch (error) {
console.error('Failed to block user:', error);
showNotification(error.message || 'Failed to block user', 'error');
}
}
@@ -4487,18 +4304,11 @@ function toggleCustomPrompt() {
const userIdStr = String(userId);
try {
const response = await fetch(`/dms/users/${userIdStr}/unblock`, { method: 'POST' });
const result = await response.json();
if (response.ok) {
await apiCall(`/dms/users/${userIdStr}/unblock`, 'POST');
showNotification(`${username} has been unblocked`);
loadBlockedUsers(); // Refresh blocked users list
} else {
throw new Error(result.message || 'Failed to unblock user');
}
} catch (error) {
console.error('Failed to unblock user:', error);
showNotification(error.message || 'Failed to unblock user', 'error');
}
}
@@ -4510,20 +4320,13 @@ function toggleCustomPrompt() {
}
try {
const response = await fetch(`/dms/users/${userIdStr}/conversations/delete-all`, { method: 'POST' });
const result = await response.json();
if (response.ok) {
await apiCall(`/dms/users/${userIdStr}/conversations/delete-all`, 'POST');
showNotification(`Bulk deletion queued for ${username} (deleting all Miku messages from Discord and logs)`);
setTimeout(() => {
loadDMUsers(); // Refresh after a delay to allow deletion to process
}, 2000);
} else {
throw new Error(result.message || 'Failed to delete conversations');
}
} catch (error) {
console.error('Failed to delete conversations:', error);
showNotification(error.message || 'Failed to delete conversations', 'error');
}
}
@@ -4541,18 +4344,11 @@ function toggleCustomPrompt() {
}
try {
const response = await fetch(`/dms/users/${userIdStr}/delete-completely`, { method: 'POST' });
const result = await response.json();
if (response.ok) {
await apiCall(`/dms/users/${userIdStr}/delete-completely`, 'POST');
showNotification(`${username} has been completely deleted from the system`);
loadDMUsers(); // Refresh the list
} else {
throw new Error(result.message || 'Failed to delete user completely');
}
} catch (error) {
console.error('Failed to delete user completely:', error);
showNotification(error.message || 'Failed to delete user completely', 'error');
}
}
@@ -4564,20 +4360,13 @@ function toggleCustomPrompt() {
}
try {
const response = await fetch(`/dms/users/${userIdStr}/conversations/${conversationId}/delete`, { method: 'POST' });
const result = await response.json();
if (response.ok) {
await apiCall(`/dms/users/${userIdStr}/conversations/${conversationId}/delete`, 'POST');
showNotification('Miku message deletion queued (deleting from both Discord and logs)');
setTimeout(() => {
viewUserConversations(userId); // Refresh after a short delay to allow deletion to process
}, 1000);
} else {
throw new Error(result.message || 'Failed to delete message');
}
} catch (error) {
console.error('Failed to delete conversation:', error);
showNotification(error.message || 'Failed to delete message', 'error');
}
}
@@ -4591,21 +4380,15 @@ function toggleCustomPrompt() {
try {
showNotification(`Analyzing ${username}'s interactions...`, 'info');
const response = await fetch(`/dms/users/${userIdStr}/analyze`, { method: 'POST' });
const result = await response.json();
const result = await apiCall(`/dms/users/${userIdStr}/analyze`, 'POST');
if (response.ok) {
if (result.reported) {
showNotification(`✅ Analysis complete! Report sent to bot owner for ${username}`);
} else {
showNotification(`📊 Analysis complete for ${username} (not enough messages or already reported today)`);
}
} else {
throw new Error(result.message || 'Failed to analyze user');
}
} catch (error) {
console.error('Failed to analyze user:', error);
showNotification(error.message || 'Failed to analyze user', 'error');
}
}
@@ -4617,17 +4400,10 @@ function toggleCustomPrompt() {
try {
showNotification('Starting DM interaction analysis...', 'info');
const response = await fetch('/dms/analysis/run', { method: 'POST' });
const result = await response.json();
if (response.ok) {
await apiCall('/dms/analysis/run', 'POST');
showNotification('✅ DM analysis completed! Check bot owner\'s DMs for any reports.');
} else {
throw new Error(result.message || 'Failed to run analysis');
}
} catch (error) {
console.error('Failed to run DM analysis:', error);
showNotification(error.message || 'Failed to run DM analysis', 'error');
}
}
@@ -4635,17 +4411,10 @@ function toggleCustomPrompt() {
try {
showNotification('Loading analysis reports...', 'info');
const response = await fetch('/dms/analysis/reports?limit=50');
const result = await response.json();
if (response.ok) {
const result = await apiCall('/dms/analysis/reports?limit=50');
displayAnalysisReports(result.reports);
} else {
throw new Error(result.message || 'Failed to load reports');
}
} catch (error) {
console.error('Failed to load reports:', error);
showNotification(error.message || 'Failed to load reports', 'error');
}
}
@@ -4736,20 +4505,13 @@ function toggleCustomPrompt() {
async function loadBlockedUsers() {
try {
const response = await fetch('/dms/blocked-users');
const result = await response.json();
if (response.ok) {
const result = await apiCall('/dms/blocked-users');
// Hide DM users list and show blocked users section
document.getElementById('dm-users-list').style.display = 'none';
document.getElementById('blocked-users-section').style.display = 'block';
displayBlockedUsers(result.blocked_users);
} else {
throw new Error(result.message || 'Failed to load blocked users');
}
} catch (error) {
console.error('Failed to load blocked users:', error);
showNotification(error.message || 'Failed to load blocked users', 'error');
}
}
@@ -4790,12 +4552,10 @@ function toggleCustomPrompt() {
async function exportAllDMs() {
try {
const response = await fetch('/dms/users');
const result = await response.json();
const result = await apiCall('/dms/users');
if (response.ok && result.users) {
let exportCount = 0;
for (const user of result.users) {
for (const user of (result.users || [])) {
try {
await exportUserDMs(user.user_id);
exportCount++;
@@ -4804,12 +4564,8 @@ function toggleCustomPrompt() {
}
}
showNotification(`Exported DMs for ${exportCount} users`);
} else {
throw new Error(result.message || 'Failed to load DM users for export');
}
} catch (error) {
console.error('Failed to export all DMs:', error);
showNotification(error.message || 'Failed to export all DMs', 'error');
}
}
@@ -4824,8 +4580,7 @@ async function loadAutonomousStats() {
}
try {
const response = await fetch('/autonomous/stats');
const data = await response.json();
const data = await apiCall('/autonomous/stats');
if (!data.servers || !data.servers[selectedGuildId]) {
document.getElementById('autonomous-stats-display').innerHTML = '<p style="color: #ff5555;">Server not found or not initialized.</p>';
@@ -4836,7 +4591,6 @@ async function loadAutonomousStats() {
displayAutonomousStats(serverData);
} catch (error) {
console.error('Failed to load autonomous stats:', error);
showNotification('Failed to load autonomous stats', 'error');
}
}
@@ -5040,8 +4794,7 @@ function toggleChatImageUpload() {
// Load voice debug mode setting from server
async function loadVoiceDebugMode() {
try {
const response = await fetch('/voice/debug-mode');
const data = await response.json();
const data = await apiCall('/voice/debug-mode');
const checkbox = document.getElementById('voice-debug-mode');
if (checkbox && data.debug_mode !== undefined) {
checkbox.checked = data.debug_mode;
@@ -5526,8 +5279,7 @@ function updateVoiceCallHistoryDisplay() {
async function refreshMemoryStats() {
try {
// Fetch Cat status
const statusRes = await fetch('/memory/status');
const statusData = await statusRes.json();
const statusData = await apiCall('/memory/status');
const indicator = document.getElementById('cat-status-indicator');
const toggleBtn = document.getElementById('cat-toggle-btn');
@@ -5547,8 +5299,7 @@ async function refreshMemoryStats() {
toggleBtn.style.borderColor = statusData.enabled ? '#4a9a4a' : '#9a4a4a';
// Fetch memory stats
const statsRes = await fetch('/memory/stats');
const statsData = await statsRes.json();
const statsData = await apiCall('/memory/stats');
if (statsData.success && statsData.collections) {
const collections = {};
@@ -5570,8 +5321,7 @@ async function refreshMemoryStats() {
async function toggleCatIntegration() {
try {
const statusRes = await fetch('/memory/status');
const statusData = await statusRes.json();
const statusData = await apiCall('/memory/status');
const newState = !statusData.enabled;
const formData = new FormData();
@@ -5599,8 +5349,7 @@ async function triggerConsolidation() {
resultDiv.style.display = 'none';
try {
const res = await fetch('/memory/consolidate', { method: 'POST' });
const data = await res.json();
const data = await apiCall('/memory/consolidate', 'POST');
if (data.success) {
status.textContent = '✅ Consolidation complete!';
@@ -5627,8 +5376,7 @@ async function loadFacts() {
listDiv.innerHTML = '<div style="text-align: center; color: #888; padding: 1rem;">Loading facts...</div>';
try {
const res = await fetch('/memory/facts');
const data = await res.json();
const data = await apiCall('/memory/facts');
if (!data.success || data.count === 0) {
listDiv.innerHTML = '<div style="text-align: center; color: #666; padding: 2rem;">No declarative facts stored yet.</div>';
@@ -5670,8 +5418,7 @@ async function loadEpisodicMemories() {
listDiv.innerHTML = '<div style="text-align: center; color: #888; padding: 1rem;">Loading memories...</div>';
try {
const res = await fetch('/memory/episodic');
const data = await res.json();
const data = await apiCall('/memory/episodic');
if (!data.success || data.count === 0) {
listDiv.innerHTML = '<div style="text-align: center; color: #666; padding: 2rem;">No episodic memories stored yet.</div>';
@@ -5712,8 +5459,7 @@ async function deleteMemoryPoint(collection, pointId, btnElement) {
if (!confirm(`Delete this ${collection} memory point?`)) return;
try {
const res = await fetch(`/memory/point/${collection}/${pointId}`, { method: 'DELETE' });
const data = await res.json();
const data = await apiCall(`/memory/point/${collection}/${pointId}`, 'DELETE');
if (data.success) {
// Remove the row from the UI
@@ -5725,7 +5471,7 @@ async function deleteMemoryPoint(collection, pointId, btnElement) {
showNotification('Failed to delete: ' + (data.error || 'Unknown error'), 'error');
}
} catch (err) {
showNotification('Error: ' + err.message, 'error');
console.error('Failed to delete memory point:', err);
}
}
@@ -5780,12 +5526,7 @@ async function executeDeleteAllMemories() {
btn.textContent = '⏳ Deleting...';
try {
const res = await fetch('/memory/delete', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ confirmation: input })
});
const data = await res.json();
const data = await apiCall('/memory/delete', 'POST', { confirmation: input });
if (data.success) {
showNotification('All memories have been permanently deleted', 'success');
@@ -5795,7 +5536,7 @@ async function executeDeleteAllMemories() {
showNotification('Deletion failed: ' + (data.error || 'Unknown error'), 'error');
}
} catch (err) {
showNotification('Error: ' + err.message, 'error');
console.error('Failed to delete all memories:', err);
} finally {
btn.disabled = false;
btn.textContent = '🗑️ Permanently Delete All Memories';
@@ -5864,17 +5605,11 @@ async function saveMemoryEdit() {
saveBtn.textContent = 'Saving...';
try {
const res = await fetch(`/memory/point/${collection}/${pointId}`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
const data = await apiCall(`/memory/point/${collection}/${pointId}`, 'PUT', {
content: content,
metadata: { source: source || 'manual_edit' }
})
});
const data = await res.json();
if (data.success) {
showNotification('Memory updated successfully', 'success');
closeEditMemoryModal();
@@ -5888,7 +5623,7 @@ async function saveMemoryEdit() {
showNotification('Failed to update: ' + (data.error || 'Unknown error'), 'error');
}
} catch (err) {
showNotification('Error: ' + err.message, 'error');
console.error('Failed to save memory edit:', err);
} finally {
saveBtn.disabled = false;
saveBtn.textContent = 'Save Changes';
@@ -5941,20 +5676,14 @@ async function saveNewMemory() {
createBtn.textContent = 'Creating...';
try {
const res = await fetch('/memory/create', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
const data = await apiCall('/memory/create', 'POST', {
collection: collection,
content: content,
user_id: userId || null,
source: source || 'manual',
metadata: {}
})
});
const data = await res.json();
if (data.success) {
showNotification(`${collection === 'declarative' ? 'Fact' : 'Memory'} created successfully`, 'success');
closeCreateMemoryModal();
@@ -5969,7 +5698,7 @@ async function saveNewMemory() {
showNotification('Failed to create: ' + (data.error || 'Unknown error'), 'error');
}
} catch (err) {
showNotification('Error: ' + err.message, 'error');
console.error('Failed to save new memory:', err);
} finally {
createBtn.disabled = false;
createBtn.textContent = 'Create Memory';