Instalação

Para Node.js, instale usando npm ou yarn:

NPM
npm install axios
package.json
{
  "name": "xtream-api-client",
  "version": "1.0.0",
  "dependencies": {
    "axios": "^1.4.0"
  },
  "type": "module"
}

Para uso no browser, inclua via CDN:

CDN
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>

Configuração

Crie a classe principal do SDK:

xtream-api.js
class XtreamAPI {
    constructor(baseUrl, username = null, password = null) {
        this.baseUrl = baseUrl.replace(/\/$/, '');
        this.username = username;
        this.password = password;
        
        // Configurar axios
        this.client = axios.create({
            baseURL: this.baseUrl,
            timeout: 30000,
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            }
        });
        
        // Interceptor para logs (opcional)
        this.client.interceptors.request.use(
            config => {
                console.log(`[API] ${config.method.toUpperCase()} ${config.url}`);
                return config;
            },
            error => Promise.reject(error)
        );
        
        this.client.interceptors.response.use(
            response => response,
            error => {
                console.error(`[API Error] ${error.message}`);
                return Promise.reject(error);
            }
        );
    }
    
    async _makeRequest(endpoint, params = {}) {
        try {
            const response = await this.client.get(endpoint, { params });
            return response.data;
        } catch (error) {
            throw new Error(`Request failed: ${error.message}`);
        }
    }
    
    async _makePostRequest(endpoint, data = {}) {
        try {
            const response = await this.client.post(endpoint, data);
            return response.data;
        } catch (error) {
            throw new Error(`Request failed: ${error.message}`);
        }
    }
}

Autenticação

Métodos para autenticação e verificação de credenciais:

Métodos de Autenticação
async authenticate(username, password) {
    const params = {
        username: username,
        password: password
    };
    
    const response = await this._makeRequest('/player_api.php', params);
    
    if (response.user_info) {
        this.username = username;
        this.password = password;
        return response;
    }
    
    throw new Error('Invalid credentials');
}

async getUserInfo() {
    if (!this.username || !this.password) {
        throw new Error('User not authenticated');
    }
    
    const params = {
        username: this.username,
        password: this.password
    };
    
    return await this._makeRequest('/player_api.php', params);
}

async panelLogin(username, password) {
    const data = new URLSearchParams({
        username: username,
        password: password
    });
    
    const response = await this._makePostRequest('/api.php?action=login', data);
    
    if (response.status === 'success') {
        return response.token;
    }
    
    throw new Error('Panel login failed');
}

Gerenciamento de Usuários

Métodos para criar, editar e gerenciar usuários:

Métodos de Usuários
async createUser(token, userData) {
    const data = new URLSearchParams({
        action: 'user',
        sub: 'create',
        token: token,
        ...userData
    });
    
    return await this._makePostRequest('/api.php', data);
}

async editUser(token, userId, userData) {
    const data = new URLSearchParams({
        action: 'user',
        sub: 'edit',
        user_id: userId,
        token: token,
        ...userData
    });
    
    return await this._makePostRequest('/api.php', data);
}

async deleteUser(token, userId) {
    const data = new URLSearchParams({
        action: 'user',
        sub: 'delete',
        user_id: userId,
        token: token
    });
    
    return await this._makePostRequest('/api.php', data);
}

async getUserDetails(token, userId) {
    const params = {
        action: 'user',
        sub: 'info',
        user_id: userId,
        token: token
    };
    
    return await this._makeRequest('/api.php', params);
}

async getAllUsers(token) {
    const params = {
        action: 'user',
        sub: 'list',
        token: token
    };
    
    return await this._makeRequest('/api.php', params);
}

Canais e Conteúdo

Métodos para gerenciar canais, VOD e séries:

Métodos de Conteúdo
async getLiveStreams() {
    const params = {
        username: this.username,
        password: this.password,
        action: 'get_live_streams'
    };
    
    return await this._makeRequest('/player_api.php', params);
}

async getVodStreams() {
    const params = {
        username: this.username,
        password: this.password,
        action: 'get_vod_streams'
    };
    
    return await this._makeRequest('/player_api.php', params);
}

async getSeries() {
    const params = {
        username: this.username,
        password: this.password,
        action: 'get_series'
    };
    
    return await this._makeRequest('/player_api.php', params);
}

async getStreamInfo(streamId, type = 'live') {
    const params = {
        username: this.username,
        password: this.password,
        action: `get_${type}_info`,
        stream_id: streamId
    };
    
    return await this._makeRequest('/player_api.php', params);
}

async getCategories(type = 'live') {
    const actionMap = {
        live: 'get_live_categories',
        vod: 'get_vod_categories',
        series: 'get_series_categories'
    };
    
    const params = {
        username: this.username,
        password: this.password,
        action: actionMap[type] || 'get_live_categories'
    };
    
    return await this._makeRequest('/player_api.php', params);
}

async getAllContent() {
    const [liveStreams, vodStreams, series] = await Promise.all([
        this.getLiveStreams(),
        this.getVodStreams(),
        this.getSeries()
    ]);
    
    return {
        liveStreams,
        vodStreams,
        series
    };
}

Relatórios

Métodos para gerar relatórios e estatísticas:

Métodos de Relatórios
async getServerStats(token) {
    const params = {
        action: 'server_stats',
        token: token
    };
    
    return await this._makeRequest('/api.php', params);
}

async getUserConnections(token, userId = null) {
    const params = {
        action: 'user_activity',
        token: token
    };
    
    if (userId) {
        params.user_id = userId;
    }
    
    return await this._makeRequest('/api.php', params);
}

async getStreamStats(token, streamId, type = 'live') {
    const params = {
        action: 'stream_stats',
        token: token,
        stream_id: streamId,
        type: type
    };
    
    return await this._makeRequest('/api.php', params);
}

Node.js

Exemplo de uso em Node.js com ES6 modules:

exemplo-nodejs.js
import axios from 'axios';
import fs from 'fs/promises';
import { XtreamAPI } from './xtream-api.js';

async function exemploCompleto() {
    try {
        // Inicializar SDK
        const api = new XtreamAPI('http://dominio_da_instancia:8080');
        
        // Autenticar usuário
        const userAuth = await api.authenticate('usuario_teste', 'senha123');
        console.log(`Usuário autenticado: ${userAuth.user_info.username}`);
        
        // Login no painel
        const token = await api.panelLogin('admin', 'admin_password');
        console.log(`Token obtido: ${token.substring(0, 10)}...`);
        
        // Criar novo usuário
        const novoUsuario = {
            username: `novo_usuario_${Date.now()}`,
            password: 'senha_forte_123',
            email: 'usuario@email.com',
            exp_date: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
            max_connections: 2,
            is_trial: 0,
            enabled: 1
        };
        
        const resultado = await api.createUser(token, novoUsuario);
        
        if (resultado.status === 'success') {
            console.log(`Usuário criado! ID: ${resultado.user_id}`);
            
            // Obter todo o conteúdo de forma paralela
            const content = await api.getAllContent();
            
            console.log(`Live Streams: ${content.liveStreams.length}`);
            console.log(`VOD Streams: ${content.vodStreams.length}`);
            console.log(`Series: ${content.series.length}`);
            
            // Salvar relatório em arquivo
            const relatorio = {
                data: new Date().toISOString(),
                usuario_criado: resultado.user_id,
                estatisticas: {
                    canais_live: content.liveStreams.length,
                    vod: content.vodStreams.length,
                    series: content.series.length
                }
            };
            
            await fs.writeFile(
                './relatorio_xtream.json', 
                JSON.stringify(relatorio, null, 2)
            );
            
            console.log('Relatório salvo em relatorio_xtream.json');
            
        } else {
            console.error(`Erro ao criar usuário: ${resultado.message}`);
        }
        
    } catch (error) {
        console.error(`Erro: ${error.message}`);
        
        // Log de erro com timestamp
        const errorLog = `${new Date().toISOString()} - ERRO: ${error.message}\n`;
        await fs.appendFile('./xtream_errors.log', errorLog);
    }
}

// Executar exemplo
exemploCompleto();

Browser

Exemplo de uso no browser com interface web:

exemplo-browser.html
<!DOCTYPE html>
<html lang="pt-BR">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Xtream API - Demo</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container mt-5">
        <h1>Xtream API Demo</h1>
        
        <div class="row">
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">
                        <h5>Autenticação</h5>
                    </div>
                    <div class="card-body">
                        <form id="authForm">
                            <div class="mb-3">
                                <label class="form-label">Servidor</label>
                                <input type="text" class="form-control" id="servidor" 
                                       value="http://dominio_da_instancia:8080">
                            </div>
                            <div class="mb-3">
                                <label class="form-label">Usuário</label>
                                <input type="text" class="form-control" id="usuario">
                            </div>
                            <div class="mb-3">
                                <label class="form-label">Senha</label>
                                <input type="password" class="form-control" id="senha">
                            </div>
                            <button type="submit" class="btn btn-primary">Conectar</button>
                        </form>
                    </div>
                </div>
            </div>
            
            <div class="col-md-6">
                <div class="card">
                    <div class="card-header">
                        <h5>Resultado</h5>
                    </div>
                    <div class="card-body">
                        <pre id="resultado"></pre>
                    </div>
                </div>
            </div>
        </div>
        
        <div class="row mt-4">
            <div class="col-12">
                <div class="card">
                    <div class="card-header">
                        <h5>Canais Disponíveis</h5>
                    </div>
                    <div class="card-body">
                        <div id="canais"></div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <script>
        class XtreamAPI {
            constructor(baseUrl) {
                this.baseUrl = baseUrl.replace(/\/$/, '');
                this.username = null;
                this.password = null;
            }
            
            async authenticate(username, password) {
                const params = new URLSearchParams({
                    username: username,
                    password: password
                });
                
                const response = await axios.get(`${this.baseUrl}/player_api.php?${params}`);
                
                if (response.data.user_info) {
                    this.username = username;
                    this.password = password;
                    return response.data;
                }
                
                throw new Error('Credenciais inválidas');
            }
            
            async getLiveStreams() {
                const params = new URLSearchParams({
                    username: this.username,
                    password: this.password,
                    action: 'get_live_streams'
                });
                
                const response = await axios.get(`${this.baseUrl}/player_api.php?${params}`);
                return response.data;
            }
        }
        
        let api = null;
        
        document.getElementById('authForm').addEventListener('submit', async (e) => {
            e.preventDefault();
            
            const servidor = document.getElementById('servidor').value;
            const usuario = document.getElementById('usuario').value;
            const senha = document.getElementById('senha').value;
            
            try {
                api = new XtreamAPI(servidor);
                const result = await api.authenticate(usuario, senha);
                
                document.getElementById('resultado').textContent = JSON.stringify(result, null, 2);
                
                // Carregar canais
                const canais = await api.getLiveStreams();
                mostrarCanais(canais.slice(0, 10)); // Primeiros 10 canais
                
            } catch (error) {
                document.getElementById('resultado').textContent = `Erro: ${error.message}`;
            }
        });
        
        function mostrarCanais(canais) {
            const container = document.getElementById('canais');
            container.innerHTML = '';
            
            canais.forEach(canal => {
                const div = document.createElement('div');
                div.className = 'alert alert-info';
                div.innerHTML = `
                    <strong>${canal.name || 'Canal sem nome'}</strong><br>
                    ID: ${canal.stream_id}<br>
                    Categoria: ${canal.category_id}
                `;
                container.appendChild(div);
            });
        }
    </script>
</body>
</html>

Tratamento de Erros

Implementação avançada de tratamento de erros e retry:

error-handling.js
class XtreamAPIAdvanced extends XtreamAPI {
    constructor(baseUrl, options = {}) {
        super(baseUrl);
        
        this.options = {
            maxRetries: options.maxRetries || 3,
            retryDelay: options.retryDelay || 1000,
            enableCache: options.enableCache || true,
            cacheTimeout: options.cacheTimeout || 300000 // 5 minutos
        };
        
        this.cache = new Map();
        this.requestQueue = new Map();
    }
    
    async _makeRequestWithRetry(endpoint, params = {}, retries = 0) {
        try {
            // Verificar cache se habilitado
            if (this.options.enableCache) {
                const cacheKey = this._getCacheKey(endpoint, params);
                const cached = this.cache.get(cacheKey);
                
                if (cached && Date.now() - cached.timestamp < this.options.cacheTimeout) {
                    console.log(`[Cache Hit] ${endpoint}`);
                    return cached.data;
                }
            }
            
            // Evitar requisições duplicadas
            const requestKey = this._getRequestKey(endpoint, params);
            if (this.requestQueue.has(requestKey)) {
                return await this.requestQueue.get(requestKey);
            }
            
            // Fazer requisição
            const requestPromise = this._makeRequest(endpoint, params);
            this.requestQueue.set(requestKey, requestPromise);
            
            const result = await requestPromise;
            
            // Salvar no cache
            if (this.options.enableCache) {
                const cacheKey = this._getCacheKey(endpoint, params);
                this.cache.set(cacheKey, {
                    data: result,
                    timestamp: Date.now()
                });
            }
            
            // Remover da fila
            this.requestQueue.delete(requestKey);
            
            return result;
            
        } catch (error) {
            this.requestQueue.delete(this._getRequestKey(endpoint, params));
            
            if (retries < this.options.maxRetries) {
                console.warn(`[Retry ${retries + 1}/${this.options.maxRetries}] ${endpoint}: ${error.message}`);
                
                // Delay antes do retry
                await new Promise(resolve => 
                    setTimeout(resolve, this.options.retryDelay * (retries + 1))
                );
                
                return this._makeRequestWithRetry(endpoint, params, retries + 1);
            }
            
            throw new Error(`Request failed after ${this.options.maxRetries} retries: ${error.message}`);
        }
    }
    
    _getCacheKey(endpoint, params) {
        return `${endpoint}:${JSON.stringify(params)}`;
    }
    
    _getRequestKey(endpoint, params) {
        return `${endpoint}:${JSON.stringify(params)}`;
    }
    
    // Sobrescrever métodos para usar retry
    async authenticate(username, password) {
        const params = { username, password };
        const response = await this._makeRequestWithRetry('/player_api.php', params);
        
        if (response.user_info) {
            this.username = username;
            this.password = password;
            return response;
        }
        
        throw new Error('Invalid credentials');
    }
    
    async getLiveStreams() {
        const params = {
            username: this.username,
            password: this.password,
            action: 'get_live_streams'
        };
        
        return await this._makeRequestWithRetry('/player_api.php', params);
    }
    
    // Método para limpar cache
    clearCache() {
        this.cache.clear();
        console.log('[Cache] Cache cleared');
    }
    
    // Método para obter estatísticas do cache
    getCacheStats() {
        return {
            size: this.cache.size,
            keys: Array.from(this.cache.keys())
        };
    }
}

// Exemplo de uso com tratamento avançado de erros
async function exemploAvancado() {
    const api = new XtreamAPIAdvanced('http://dominio_da_instancia:8080', {
        maxRetries: 5,
        retryDelay: 2000,
        enableCache: true,
        cacheTimeout: 600000 // 10 minutos
    });
    
    try {
        // Tentar autenticar com retry automático
        await api.authenticate('usuario_teste', 'senha123');
        console.log('Autenticado com sucesso!');
        
        // Múltiplas chamadas para testar cache
        console.time('Primeira chamada');
        const canais1 = await api.getLiveStreams();
        console.timeEnd('Primeira chamada');
        
        console.time('Segunda chamada (cache)');
        const canais2 = await api.getLiveStreams();
        console.timeEnd('Segunda chamada (cache)');
        
        console.log('Cache stats:', api.getCacheStats());
        
    } catch (error) {
        console.error('Erro final:', error.message);
        
        // Análise do erro
        if (error.message.includes('Network Error')) {
            console.error('Problema de conectividade');
        } else if (error.message.includes('credentials')) {
            console.error('Problema de autenticação');
        } else {
            console.error('Erro desconhecido');
        }
    }
}

exemploAvancado();
Dica: O SDK JavaScript oferece funcionalidades avançadas como cache automático, retry com backoff e prevenção de requisições duplicadas para otimizar performance.