Interfaccia Third-Party
Crea uno strumento che BakoshApp possa pilotare: esponi quattro endpoint HTTP su una porta locale, e il tuo programma reagirà a regali, like, follow e chat di TikTok e Kick.
BakoshApp può eseguire azioni all'interno del tuo programma. Il tuo strumento espone una piccola API HTTP su una porta locale; BakoshApp legge la tua lista di azioni e ne chiama una ogni volta che un evento TikTok o Kick corrisponde al trigger dell'utente. Tutto ciò che puoi controllare da codice — luci smart, un microcontrollore, una soundboard, un altro gioco, il tuo bot — può reagire a una live senza un mod di BakoshApp.
Come funziona nell'insieme
- Il tuo strumento è in ascolto su
http://127.0.0.1:8833. - L'utente lo collega in Impostazioni → Third-Party (host e porta) e lo verifica con Prova connessione.
- Nella scheda Azioni di un mod, l'utente clicca su Aggiungi nuovo, sceglie un trigger e in Tutte le azioni → Esterni configura una Third-Party Action: BakoshApp compila due liste con le tue categorie e azioni.
- Ad ogni evento corrispondente, BakoshApp chiama il tuo strumento, e il tuo codice fa il resto.
La connessione è a senso unico: BakoshApp chiama te, mai il contrario.
Porta e indirizzo
- 8833 è la porta predefinita. L'utente può cambiarla in Impostazioni → Third-Party; se usi una porta diversa, indica ai tuoi utenti quale inserire.
- La porta 8832 non può essere usata: BakoshApp stesso è in ascolto lì (è così che TikFinity trova BakoshApp), e l'impostazione la rifiuta.
- Non c'è autenticazione. Resta in ascolto su
127.0.0.1, non su0.0.0.0, in modo che l'API non sia raggiungibile dalla rete. - BakoshApp usa sempre HTTP semplice.
Endpoint
Il tuo strumento deve fornire tutti e quattro. Ogni risposta è in JSON con un membro data.
1. Info app
Identifica il tuo strumento. BakoshApp lo mostra come "Connesso con Mock Tool 1.0 di Bakosh" in Impostazioni e nel configuratore delle azioni.
GET /api/app/info
{ "data": { "name": "Mock Tool", "version": "1.0", "author": "Bakosh" } }2. Categorie
La prima lista nel configuratore.
GET /api/features/categories
{
"data": [
{ "categoryId": "smart_device_control", "categoryName": "Control Smart Devices" },
{ "categoryId": "serial_port_control", "categoryName": "Control Serial Port" }
]
}3. Azioni
La seconda lista: le azioni di una categoria. categoryId è URL-encoded.
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" }
]
}Le liste mostrano i tuoi elementi nell'ordine in cui li restituisci. Un'azione che l'utente ha già salvato ma che non restituisci più resta in cima alla lista, così non cambia silenziosamente.
categoryId e actionId sono tutto ciò che BakoshApp memorizza per un'azione configurata. Mantienili stabili: rinominare un id rompe le configurazioni esistenti. I nomi servono solo per la visualizzazione e possono cambiare in qualsiasi momento.
4. Esecuzione
Chiamato ogni volta che un evento corrispondente esegue l'azione.
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://…"
}
}Rispondi con un array data vuoto una volta accettata la richiesta:
{ "data": [] }Tempistiche
- BakoshApp attende fino a 5 secondi per i tre endpoint GET e 10 secondi per
exec. Una richiesta che fallisce o va in timeout non viene ripetuta. - Se l'azione ha Quantità superiore a 1, BakoshApp chiama
execaltrettante volte, una dopo l'altra: attende la tua risposta, poi l'Intervallo della riga, poi chiama di nuovo. - Le chiamate per la stessa riga arrivano una alla volta; righe diverse possono chiamarti in parallelo.
Quindi rispondi rapidamente ed esegui i lavori lenti in background — gli spettatori possono inviare regali più velocemente di quanto si muova una porta seriale.
L'oggetto context
context descrive l'evento che ha eseguito l'azione. Sono presenti solo i campi che esistono per quell'evento — verifica prima di leggerli.
| Campo | Tipo | Presente |
|---|---|---|
triggerTypeId | numero | sempre — vedi sotto |
eventType | stringa | sempre — gift, like, chat, follow, share, joined, subscribe, tikfinity o test |
source | stringa | sempre — eulerstream (TikTok), kick, tikfinity o test |
platform | stringa | Eventi TikTok e Kick — tiktok o kick |
username | stringa | sempre — l'handle dello spettatore |
nickname | stringa | Eventi TikTok e Kick — il nome visualizzato |
userId | stringa | Eventi TikTok e Kick |
profilePictureUrl | stringa | di solito (i link agli avatar di TikTok scadono) |
comment | stringa | messaggi in chat; su Kick anche il messaggio allegato a un regalo |
giftName | stringa | regali |
giftId | numero | Regali TikTok |
repeatCount | numero | Regali TikTok — regali nella serie; abbonamenti regalati su Kick — numero di destinatari |
diamondCount | numero | regali — valore in Diamonds (TikTok) o prezzo in Kicks (Kick) |
coins | numero | come diamondCount |
likeCount | numero | like |
subMonth | numero | abbonamenti |
Gli eventi inoltrati da TikFinity contengono solo triggerTypeId (sempre 0), source, eventType e username.
Tipi di trigger
triggerTypeId è il tipo di trigger configurato dall'utente, così un regalo scelto per nome e uno individuato per valore vengono distinti:
| Id | Trigger |
|---|---|
| 1 | Condivisione |
| 3 | Min-Max (intervallo di valore del regalo) |
| 4 | Regalo |
| 6 | Entrato |
| 7 | Like |
| 9 | Segui |
| 10 | Subscribe / Super Fan |
| 11 | Chat |
| 0 | TikFinity, o qualsiasi altra cosa |
Tratta gli id sconosciuti come 0; potrebbero esserne aggiunti altri.
Il pulsante Prova
Prova sulla riga dell'azione (e la sua scorciatoia) chiama exec con dati di esempio: source e eventType sono test, triggerTypeId proviene dal trigger della riga, lo spettatore è bakosh_app, e il regalo è una Rose (giftId 5655). Non c'è platform.
Segnalare i problemi
Restituisci un message per descrivere cosa è andato storto:
{ "message": "Serial port COM3 is not available" }- Sugli endpoint GET, qualsiasi
messagefa sì che BakoshApp tratti la risposta come un errore, anche con HTTP 200. - Su
exec, ilmessageviene scritto nella console e nel file di log di BakoshApp come avviso. L'utente non riceve alcun popup.
Vengono rispettati anche gli status HTTP di errore; senza un message, il log mostra solo il codice di stato.
Funzionare anche con TikFinity
L'interfaccia corrisponde all'interfaccia third-party di TikFinity — gli stessi quattro percorsi e nomi di campo — quindi uno strumento può servire entrambi. Le porte differiscono: TikFinity cerca gli strumenti sulla 8832, che BakoshApp occupa mentre è in esecuzione, quindi assegna a BakoshApp un'altra porta.
TikFinity è una web app e ha bisogno di header CORS (Access-Control-Allow-Origin: * e simili) oltre che di risposte alle richieste preflight OPTIONS. BakoshApp non ne ha bisogno, ma inviarli non fa danno. BakoshApp invia più campi context di TikFinity — ignora quelli che non usi.
Uno strumento completo e funzionante
Nessuna dipendenza — salvalo come tool.mjs ed esegui 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}`));Testare il tuo strumento
- Avvia il tuo strumento.
- In BakoshApp, apri Impostazioni → Third-Party, verifica host e porta, e clicca su Prova connessione. Dovresti vedere il nome, la versione e l'autore del tuo strumento.
- Nella scheda Azioni di un mod, clicca su Aggiungi nuovo, scegli un trigger e clicca su Avanti. In Tutte le azioni → Esterni, clicca su Configure accanto a Third-Party Action, scegli la tua categoria e azione, e salva.
- Clicca su Prova sulla nuova riga — il tuo strumento riceve un
execconeventType: "test". - Vai in diretta e verifica che arrivino eventi reali.
Se il configuratore dice "Impossibile connettersi! Controlla la tua integrazione.", verifica che lo strumento sia in ascolto su 127.0.0.1, che la porta corrisponda a quella in Impostazioni, e che GET /api/app/info restituisca la risposta dentro data.