222 lines
7 KiB
JavaScript
222 lines
7 KiB
JavaScript
// API Communication Module
|
|
// Handles all AJAX/Fetch calls and API interactions
|
|
|
|
(function() {
|
|
'use strict';
|
|
|
|
AppModules.register('api');
|
|
|
|
const API_BASE_URL = '';
|
|
|
|
// Generic fetch wrapper with error handling and retries
|
|
function apiRequest(endpoint, options = {}) {
|
|
const url = endpoint.startsWith('?') ? endpoint : `${API_BASE_URL}${endpoint}`;
|
|
|
|
return fetch(url, {
|
|
method: options.method || 'GET',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded',
|
|
...options.headers
|
|
},
|
|
body: options.body
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.catch(error => {
|
|
AppLogger.error(`API request to ${endpoint} failed:`, error);
|
|
throw error;
|
|
});
|
|
}
|
|
|
|
// Stream status checking
|
|
function checkStreamStatus() {
|
|
return apiRequest('?api=stream_status')
|
|
.then(data => {
|
|
AppLogger.log('Stream status check:', data);
|
|
return data.online === true;
|
|
})
|
|
.catch(error => {
|
|
AppLogger.error('Stream status check failed:', error);
|
|
return false; // Assume offline if check fails
|
|
});
|
|
}
|
|
|
|
// User management
|
|
function getUserId() {
|
|
return apiRequest('', {
|
|
method: 'POST',
|
|
body: 'action=get_user_id'
|
|
})
|
|
.then(data => {
|
|
if (data.success) {
|
|
AppState.userId = data.user_id;
|
|
AppState.isAdmin = data.is_admin || false;
|
|
|
|
const userIdElement = document.getElementById('userId');
|
|
if (userIdElement) {
|
|
userIdElement.textContent = '#' + AppState.userId;
|
|
|
|
if (AppState.isAdmin) {
|
|
userIdElement.classList.add('admin');
|
|
userIdElement.textContent = '👑 #' + AppState.userId;
|
|
const adminControls = document.getElementById('adminControls');
|
|
if (adminControls) adminControls.style.display = 'flex';
|
|
}
|
|
}
|
|
|
|
return data;
|
|
} else {
|
|
throw new Error('Failed to get user ID');
|
|
}
|
|
});
|
|
}
|
|
|
|
// Heartbeat functionality
|
|
function sendHeartbeat() {
|
|
const nicknameValue = document.getElementById('nickname')?.value || 'Anonymous';
|
|
|
|
return apiRequest('', {
|
|
method: 'POST',
|
|
body: `action=heartbeat&nickname=${encodeURIComponent(nicknameValue)}`
|
|
})
|
|
.then(data => {
|
|
if (data.success && data.viewer_count !== undefined) {
|
|
AppState.viewerCount = data.viewer_count;
|
|
updateViewerCount(data.viewer_count);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
AppLogger.error('Heartbeat failed:', error);
|
|
});
|
|
}
|
|
|
|
// Chat message operations
|
|
function sendMessage(nickname, message) {
|
|
if (!nickname || !message) {
|
|
throw new Error('Nickname and message are required');
|
|
}
|
|
|
|
const body = `action=send&nickname=${encodeURIComponent(nickname)}&message=${encodeURIComponent(message)}`;
|
|
|
|
return apiRequest('', {
|
|
method: 'POST',
|
|
body: body
|
|
});
|
|
}
|
|
|
|
function fetchMessages() {
|
|
return apiRequest('', {
|
|
method: 'POST',
|
|
body: `action=fetch&last_id=${encodeURIComponent(AppState.lastMessageId)}`
|
|
})
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Update viewer count
|
|
if (data.viewer_count !== undefined) {
|
|
AppState.viewerCount = data.viewer_count;
|
|
updateViewerCount(data.viewer_count);
|
|
}
|
|
|
|
return data;
|
|
} else {
|
|
throw new Error('Failed to fetch messages');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
AppLogger.error('Fetch messages failed:', error);
|
|
updateConnectionStatus(false);
|
|
throw error;
|
|
});
|
|
}
|
|
|
|
// Admin functions
|
|
function deleteMessage(messageId) {
|
|
if (!AppState.isAdmin) return Promise.reject(new Error('Admin access required'));
|
|
|
|
return apiRequest('', {
|
|
method: 'POST',
|
|
body: `action=delete_message&message_id=${encodeURIComponent(messageId)}`
|
|
})
|
|
.then(data => {
|
|
if (data.success) {
|
|
return data;
|
|
} else {
|
|
throw new Error('Failed to delete message');
|
|
}
|
|
});
|
|
}
|
|
|
|
function banUser(userId) {
|
|
if (!AppState.isAdmin) return Promise.reject(new Error('Admin access required'));
|
|
|
|
return apiRequest('', {
|
|
method: 'POST',
|
|
body: `action=ban_user&user_id=${encodeURIComponent(userId)}`
|
|
})
|
|
.then(data => {
|
|
if (data.success) {
|
|
return data;
|
|
} else {
|
|
throw new Error('Failed to ban user');
|
|
}
|
|
});
|
|
}
|
|
|
|
function clearChat() {
|
|
if (!AppState.isAdmin) return Promise.reject(new Error('Admin access required'));
|
|
|
|
return apiRequest('', {
|
|
method: 'POST',
|
|
body: 'action=clear_chat'
|
|
})
|
|
.then(data => {
|
|
if (data.success) {
|
|
return data;
|
|
} else {
|
|
throw new Error('Failed to clear chat');
|
|
}
|
|
});
|
|
}
|
|
|
|
// UI feedback functions (will be moved to ui-controls later, but needed here for now)
|
|
function updateViewerCount(count) {
|
|
const viewerElement = document.getElementById('viewerCount');
|
|
if (viewerElement) {
|
|
viewerElement.textContent = count + (count === 1 ? ' viewer' : ' viewers');
|
|
}
|
|
}
|
|
|
|
function updateConnectionStatus(online) {
|
|
const statusDot = document.getElementById('statusDot');
|
|
const statusText = document.getElementById('statusText');
|
|
|
|
if (statusDot && statusText) {
|
|
if (online) {
|
|
statusDot.classList.remove('offline');
|
|
statusText.textContent = 'Connected';
|
|
} else {
|
|
statusDot.classList.add('offline');
|
|
statusText.textContent = 'Reconnecting...';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Public API
|
|
window.API = {
|
|
checkStreamStatus: checkStreamStatus,
|
|
getUserId: getUserId,
|
|
sendHeartbeat: sendHeartbeat,
|
|
sendMessage: sendMessage,
|
|
fetchMessages: fetchMessages,
|
|
deleteMessage: deleteMessage,
|
|
banUser: banUser,
|
|
clearChat: clearChat
|
|
};
|
|
|
|
AppLogger.log('API module loaded');
|
|
|
|
})();
|