iptv-stream-web/assets/js/api.js

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');
})();