Skip to content

How come you get access tokens? I don't understand. #140

@Benzitczo

Description

@Benzitczo
require('dotenv').config();
const cloudscraper = require('cloudscraper');
const { KickClient } = require('@botk4cp3r/kick.js');
const initDatabase = require('./database');
const fs = require('fs');
const path = require('path');

// Bloqueo para evitar ejecución múltiple
const lockFile = path.join(__dirname, 'bot.lock');
try {
    if (fs.existsSync(lockFile)) {
        const lockContent = fs.readFileSync(lockFile, 'utf8');
        console.log(`Script ya está ejecutándose (PID: ${lockContent}), saliendo...`);
        process.exit(0);
    }
    fs.writeFileSync(lockFile, process.pid.toString());
} catch (error) {
    console.error('Error al manejar lock file:', error.message);
    process.exit(1);
}

// Limpiar lock file al salir
process.on('exit', () => {
    try {
        if (fs.existsSync(lockFile)) {
            fs.unlinkSync(lockFile);
            console.log('Lock file eliminado');
        }
    } catch (error) {
        console.error('Error al eliminar lock file:', error.message);
    }
});
process.on('SIGINT', () => process.exit(0));
process.on('SIGTERM', () => process.exit(0));

let giveawayActive = false;
let participants = [];
let endTime = null;

(async () => {
    // Conectar a la base de datos
    let db;
    try {
        db = await initDatabase();
        console.log('Conectado a la base de datos');
    } catch (error) {
        console.error('Error al conectar a la base de datos:', error.message);
        return;
    }

    // Verificar variables de entorno
    const requiredEnvVars = ['KICK_CHANNEL', 'CLIENT_ID', 'CLIENT_SECRET', 'BROADCASTER_USER_ID'];
    for (const envVar of requiredEnvVars) {
        if (!process.env[envVar]) {
            console.error(`Error: ${envVar} no está definido en .env`);
            return;
        }
    }

    // Obtener access_token con cloudscraper
    let accessToken;
    try {
        const response = await cloudscraper({
            method: 'POST',
            url: 'https://id.kick.com/oauth/token',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },
            body: new URLSearchParams({
                grant_type: 'client_credentials',
                client_id: process.env.CLIENT_ID,
                client_secret: process.env.CLIENT_SECRET
            }).toString(),
            cloudflareMaxTimeout: 30000,
            challengesToSolve: 3
        });
        const data = JSON.parse(response);
        if (!data.access_token) {
            throw new Error('No se recibió access_token');
        }
        accessToken = data.access_token;
        console.log('Access token obtenido correctamente');
    } catch (error) {
        console.error('Error al obtener access_token:', error.message);
        return;
    }

    // Obtener broadcaster_user_id
    let broadcasterUserId = process.env.BROADCASTER_USER_ID;
    const broadcasterUserIdNum = parseInt(broadcasterUserId, 10);
    if (isNaN(broadcasterUserIdNum) || broadcasterUserIdNum <= 0) {
        console.error('Error: BROADCASTER_USER_ID debe ser un número válido');
        return;
    }
    console.log('Usando BROADCASTER_USER_ID de .env:', broadcasterUserIdNum);

    // Crear instancia del cliente
    const clientOptions = {
        token: accessToken,
        channel: process.env.KICK_CHANNEL,
        broadcaster_user_id: broadcasterUserIdNum,
        broadcaster_id: broadcasterUserId // Prueba ambos formatos
    };
    console.log('Inicializando KickClient con:', {
        channel: clientOptions.channel,
        broadcaster_user_id: clientOptions.broadcaster_user_id,
        broadcaster_id: clientOptions.broadcaster_id
    });
    let client;
    try {
        client = new KickClient(clientOptions);
        console.log('KickClient creado correctamente');
    } catch (error) {
        console.error('Error al crear KickClient:', error.message);
        console.error('Parámetros enviados:', clientOptions);
        return;
    }

    // Intentar inicializar el cliente para eventos de chat
    try {
        await client.subscribeToEvents(['chat.message.sent']);
        console.log('Conectado al chat de Kick');
    } catch (error) {
        console.error('Error al inicializar el cliente:', error.message);
        console.error('Parámetros enviados a KickClient:', clientOptions);
        return;
    }

    // Escuchar mensajes del chat
    client.on('chatMessage', async (message) => {
        try {
            const sender = message.sender.username;
            const content = message.content;
            const args = content.split(' ');

            if (content.startsWith('!giveaway')) {
                const subcommand = args[1]?.toLowerCase();

                if (subcommand === 'start' && args[2]) {
                    if (!giveawayActive) {
                        const minutes = parseInt(args[2]);
                        if (isNaN(minutes) || minutes <= 0) {
                            await client.sendChatMessage({ content: 'Por favor, indica un número válido de minutos.' });
                            return;
                        }
                        giveawayActive = true;
                        participants = [];
                        endTime = new Date(Date.now() + minutes * 60 * 1000);

                        await db.query('INSERT INTO giveaways (active, end_time, participants) VALUES (?, ?, ?)', [
                            true,
                            endTime,
                            JSON.stringify(participants)
                        ]);

                        await client.sendChatMessage({ content: `¡Sorteo iniciado! Dura ${minutes} minutos. Usa !giveaway join para participar.` });
                        setTimeout(async () => {
                            if (giveawayActive) {
                                await endGiveaway(db, client);
                            }
                        }, minutes * 60 * 1000);
                    } else {
                        await client.sendChatMessage({ content: 'Ya hay un sorteo activo.' });
                    }
                }

                if (subcommand === 'join') {
                    if (giveawayActive) {
                        if (!participants.includes(sender)) {
                            participants.push(sender);
                            await db.query('UPDATE giveaways SET participants = ? WHERE active = TRUE', [
                                JSON.stringify(participants)
                            ]);
                            await client.sendChatMessage({ content: `${sender} ha entrado al sorteo.` });
                        } else {
                            await client.sendChatMessage({ content: `${sender}, ya estás en el sorteo.` });
                        }
                    } else {
                        await client.sendChatMessage({ content: 'No hay un sorteo activo.' });
                    }
                }

                if (subcommand === 'participants') {
                    if (giveawayActive) {
                        await client.sendChatMessage({ content: `Participantes: ${participants.join(', ') || 'Ninguno'}` });
                    } else {
                        await client.sendChatMessage({ content: 'No hay un sorteo activo.' });
                    }
                }

                if (subcommand === 'end') {
                    if (giveawayActive) {
                        await endGiveaway(db, client);
                    } else {
                        await client.sendChatMessage({ content: 'No hay un sorteo activo.' });
                    }
                }

                if (subcommand === 'enable') {
                    giveawayActive = true;
                    await db.query('UPDATE giveaways SET active = TRUE WHERE id = (SELECT MAX(id) FROM giveaways)');
                    await client.sendChatMessage({ content: 'Sorteos habilitados.' });
                }

                if (subcommand === 'disable') {
                    giveawayActive = false;
                    await db.query('UPDATE giveaways SET active = FALSE WHERE id = (SELECT MAX(id) FROM giveaways)');
                    await client.sendChatMessage({ content: 'Sorteos deshabilitados.' });
                }
            }
        } catch (error) {
            console.error('Error al procesar mensaje:', error.message);
        }
    });

    // Manejar errores del cliente
    client.on('error', (error) => {
        console.error('Error en el cliente:', error.message);
    });

    // Manejar desconexión
    client.on('close', async () => {
        console.log('Desconectado del chat, intentando reconectar...');
        try {
            const tokenResponse = await cloudscraper({
                method: 'POST',
                url: 'https://id.kick.com/oauth/token',
                headers: {
                    'Content-Type': 'application/x-www-form-urlencoded'
                },
                body: new URLSearchParams({
                    grant_type: 'client_credentials',
                    client_id: process.env.CLIENT_ID,
                    client_secret: process.env.CLIENT_SECRET
                }).toString(),
                cloudflareMaxTimeout: 30000,
                challengesToSolve: 3
            });
            const tokenData = JSON.parse(tokenResponse);
            if (!tokenData.access_token) {
                throw new Error('No se recibió access_token');
            }
            accessToken = tokenData.access_token;
            client.token = accessToken;
            await client.subscribeToEvents(['chat.message.sent']);
            console.log('Reconectado al chat de Kick');
        } catch (error) {
            console.error('Error al reconectar:', error.message);
        }
    });

    async function endGiveaway(db, client) {
        if (participants.length > 0) {
            const winner = participants[Math.floor(Math.random() * participants.length)];
            await client.sendChatMessage({ content: `¡El sorteo ha terminado! El ganador es: ${winner}` });
        } else {
            await client.sendChatMessage({ content: 'El sorteo ha terminado, pero no hubo participantes.' });
        }
        giveawayActive = false;
        participants = [];
        endTime = null;
        await db.query('UPDATE giveaways SET active = FALSE, participants = ? WHERE active = TRUE', [
            JSON.stringify([])
        ]);
    }
})();

===

KICK_CHANNEL=benzitczo
CLIENT_ID=
CLIENT_SECRET=
ACCESS_TOKEN=
BROADCASTER_USER_ID=


Oh sorry, that's bot hosting, this Pterodacty, for if I can, right? and how explain where is acces tokens?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions