Interfaz Third-Party
Crea una herramienta que BakoshApp pueda controlar: sirve cuatro endpoints HTTP en un puerto local y tu programa reaccionará a los regalos, likes, nuevos seguidores y mensajes del chat de TikTok y Kick.
BakoshApp puede ejecutar acciones dentro de tu programa. Tu herramienta sirve una pequeña API HTTP en un puerto local; BakoshApp lee tu lista de acciones y llama a una cada vez que un evento de TikTok o Kick coincide con el disparador del usuario. Cualquier cosa que puedas controlar desde código (luces inteligentes, un microcontrolador, una botonera de sonidos, otro juego, tu propio bot) puede reaccionar a un directo sin un mod de BakoshApp.
Cómo encaja todo
- Tu herramienta escucha en
http://127.0.0.1:8833. - El usuario la conecta en Ajustes → Third-Party (host y puerto) y la comprueba con Probar conexión.
- En la pestaña Acciones de un mod, el usuario hace clic en Añadir nuevo, elige un disparador y, en Todas las acciones → Externos, configura una Third-Party Action: BakoshApp rellena dos listas con tus categorías y tus acciones.
- En cada evento que coincide, BakoshApp llama a tu herramienta y tu código hace el trabajo.
La conexión es unidireccional: BakoshApp te llama a ti, nunca al revés.
Puerto y dirección
- 8833 es el puerto predeterminado. El usuario puede cambiarlo en Ajustes → Third-Party; si usas otro, indica a tus usuarios qué puerto deben introducir.
- El 8832 no se puede usar: ahí escucha el propio BakoshApp (así es como TikFinity encuentra BakoshApp), y el ajuste lo rechaza.
- No hay autenticación. Escucha en
127.0.0.1, no en0.0.0.0, para que la API no sea accesible desde la red. - BakoshApp siempre usa HTTP simple, sin cifrado.
Endpoints
Tu herramienta debe servir los cuatro. Cada respuesta es un JSON con un miembro data.
1. Información de la app
Identifica tu herramienta. BakoshApp la muestra como «Conectado con Mock Tool 1.0 de Bakosh» en Ajustes y en el configurador de acciones.
GET /api/app/info
{ "data": { "name": "Mock Tool", "version": "1.0", "author": "Bakosh" } }2. Categorías
La primera lista del configurador.
GET /api/features/categories
{
"data": [
{ "categoryId": "smart_device_control", "categoryName": "Control Smart Devices" },
{ "categoryId": "serial_port_control", "categoryName": "Control Serial Port" }
]
}3. Acciones
La segunda lista: las acciones de una categoría. categoryId se envía codificado para URL.
GET /api/features/actions?categoryId=smart_device_control
{
"data": [
{ "actionId": "turn_lights_on", "actionName": "Turn Lights On" },
{ "actionId": "turn_lights_off", "actionName": "Turn Lights Off" }
]
}Las listas muestran tus elementos en el orden en que los devuelves. Una acción que el usuario ya guardó pero que ya no devuelves se queda al principio de la lista, para que no cambie sin avisar.
categoryId y actionId son todo lo que BakoshApp guarda de una acción configurada. Mantenlos estables: renombrar un id rompe las configuraciones existentes. Los nombres solo sirven para mostrarse y pueden cambiar en cualquier momento.
4. Ejecutar
Se llama cada vez que un evento que coincide ejecuta la acción.
POST /api/features/actions/exec
{
"categoryId": "smart_device_control",
"actionId": "turn_lights_on",
"context": {
"triggerTypeId": 4,
"eventType": "gift",
"source": "eulerstream",
"platform": "tiktok",
"userId": "123456789",
"username": "testuser",
"nickname": "Test User",
"giftName": "Rose",
"giftId": 5655,
"repeatCount": 3,
"diamondCount": 1,
"coins": 1,
"profilePictureUrl": "https://…"
}
}Responde con un array data vacío en cuanto hayas aceptado la solicitud:
{ "data": [] }Tiempos
- BakoshApp espera hasta 5 segundos a los tres endpoints GET y 10 segundos a
exec. Una solicitud que falla o agota el tiempo de espera no se repite. - Si la acción tiene una Cantidad mayor que 1, BakoshApp llama a
execese número de veces, una tras otra: espera tu respuesta, luego el Intervalo de la fila, y vuelve a llamar. - Las llamadas de una misma fila llegan de una en una; filas distintas pueden llamarte en paralelo.
Así que responde rápido y haz el trabajo lento en segundo plano: los espectadores pueden enviar regalos más rápido de lo que da de sí un puerto serie.
El objeto context
context describe el evento que ejecutó la acción. Solo están presentes los campos que existen para ese evento: compruébalos antes de leerlos.
| Campo | Tipo | Cuándo aparece |
|---|---|---|
triggerTypeId | number | siempre — ver más abajo |
eventType | string | siempre — gift, like, chat, follow, share, joined, subscribe, tikfinity o test |
source | string | siempre — eulerstream (TikTok), kick, tikfinity o test |
platform | string | eventos de TikTok y Kick — tiktok o kick |
username | string | siempre — el nombre de usuario del espectador |
nickname | string | eventos de TikTok y Kick — el nombre visible |
userId | string | eventos de TikTok y Kick |
profilePictureUrl | string | normalmente (los enlaces de avatar de TikTok caducan) |
comment | string | mensajes de chat; en Kick, también el mensaje que acompaña a un regalo |
giftName | string | regalos |
giftId | number | regalos de TikTok |
repeatCount | number | regalos de TikTok — regalos de la racha; suscripciones regaladas de Kick — número de destinatarios |
diamondCount | number | regalos — valor en diamantes (TikTok) o precio en Kicks (Kick) |
coins | number | igual que diamondCount |
likeCount | number | likes |
subMonth | number | suscripciones |
Los eventos reenviados desde TikFinity solo traen triggerTypeId (siempre 0), source, eventType y username.
Tipos de disparador
triggerTypeId es el tipo de disparador que configuró el usuario; así se distingue un regalo elegido por su nombre de un regalo que coincide por su valor:
| Id | Disparador |
|---|---|
| 1 | Compartir |
| 3 | Mín-Máx (rango de valor del regalo) |
| 4 | Regalo |
| 6 | Se unió |
| 7 | Like |
| 9 | Seguir |
| 10 | Subscribe / Super Fan |
| 11 | Chat |
| 0 | TikFinity o cualquier otro |
Trata los ids desconocidos como 0; pueden añadirse más.
El botón Probar
Probar en la fila de la acción (y su tecla rápida) llama a exec con datos de ejemplo: source y eventType son test, triggerTypeId viene del disparador de la fila, el espectador es bakosh_app y el regalo es una Rose (giftId 5655). No hay platform.
Informar de problemas
Devuelve un message para describir qué salió mal:
{ "message": "Serial port COM3 is not available" }- En los endpoints GET, cualquier
messagehace que BakoshApp trate la respuesta como un error, incluso con HTTP 200. - En
exec, elmessagese escribe como advertencia en la consola y en el archivo de registro de BakoshApp. El usuario no ve ninguna ventana emergente.
También se respetan los códigos de estado HTTP de error; sin un message, el registro solo muestra el código de estado.
Trabajar también con TikFinity
La interfaz coincide con la interfaz de terceros de TikFinity (las mismas cuatro rutas y los mismos nombres de campo), así que una misma herramienta puede servir a las dos. Los puertos son distintos: TikFinity busca herramientas en el 8832, que BakoshApp ocupa mientras se ejecuta, así que asigna a BakoshApp otro puerto.
TikFinity es una app web y necesita cabeceras CORS (Access-Control-Allow-Origin: * y compañía), además de respuestas a las solicitudes de preflight OPTIONS. BakoshApp no las necesita, pero enviarlas no hace daño. BakoshApp envía más campos de context que TikFinity: ignora los que no uses.
Una herramienta completa que funciona
Sin dependencias: guárdala como tool.mjs y ejecuta node tool.mjs:
import http from 'node:http';
const PORT = 8833;
const APP_INFO = { name: 'Mock Tool', version: '1.0', author: 'Bakosh' };
const CATALOG = [
{
categoryId: 'smart_device_control',
categoryName: 'Control Smart Devices',
actions: [
{ actionId: 'turn_lights_on', actionName: 'Turn Lights On' },
{ actionId: 'turn_lights_off', actionName: 'Turn Lights Off' },
],
},
];
// Wildcard CORS keeps the same tool usable from TikFinity as well.
const CORS = {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Headers': '*',
'Access-Control-Allow-Methods': '*',
};
const send = (res, status, body) => {
res.writeHead(status, { 'Content-Type': 'application/json', ...CORS });
res.end(JSON.stringify(body));
};
const readBody = (req) =>
new Promise((resolve) => {
let raw = '';
req.on('data', (c) => { raw += c; });
req.on('end', () => { try { resolve(JSON.parse(raw || '{}')); } catch { resolve({}); } });
});
// Your actual work goes here. Return a string to report a problem.
function runAction(categoryId, actionId, context) {
console.log(`${categoryId}/${actionId} fired by ${context.username ?? 'someone'} on ${context.platform ?? context.source}`);
// turnLightsOn() …
return null;
}
http.createServer(async (req, res) => {
const url = new URL(req.url, `http://127.0.0.1:${PORT}`);
if (req.method === 'OPTIONS') { // preflight (TikFinity only)
res.writeHead(204, CORS);
return res.end();
}
if (req.method === 'GET' && url.pathname === '/api/app/info') {
return send(res, 200, { data: APP_INFO });
}
if (req.method === 'GET' && url.pathname === '/api/features/categories') {
return send(res, 200, {
data: CATALOG.map(({ categoryId, categoryName }) => ({ categoryId, categoryName })),
});
}
if (req.method === 'GET' && url.pathname === '/api/features/actions') {
const cat = CATALOG.find((c) => c.categoryId === url.searchParams.get('categoryId'));
return send(res, 200, { data: cat ? cat.actions : [] });
}
if (req.method === 'POST' && url.pathname === '/api/features/actions/exec') {
const body = await readBody(req);
const problem = runAction(body.categoryId ?? '', body.actionId ?? '', body.context ?? {});
return problem ? send(res, 200, { message: problem }) : send(res, 200, { data: [] });
}
send(res, 404, { message: `No such endpoint: ${url.pathname}` });
}).listen(PORT, '127.0.0.1', () => console.log(`Listening on http://127.0.0.1:${PORT}`));Probar tu herramienta
- Inicia tu herramienta.
- En BakoshApp, abre Ajustes → Third-Party, comprueba el host y el puerto y haz clic en Probar conexión. Deberías ver el nombre, la versión y el autor de tu herramienta.
- En la pestaña Acciones de un mod, haz clic en Añadir nuevo, elige un disparador y haz clic en Siguiente. En Todas las acciones → Externos, haz clic en Configure junto a Third-Party Action, elige tu categoría y tu acción, y guarda.
- Haz clic en Probar en la nueva fila: tu herramienta recibe un
execconeventType: "test". - Empieza un directo y comprueba que llegan eventos reales.
Si el configurador dice «¡No se pudo conectar! Revisa tu integración.», comprueba que la herramienta escucha en 127.0.0.1, que el puerto coincide con el de Ajustes y que GET /api/app/info devuelve su respuesta dentro de data.