Antarmuka Third-Party

Bangun tool yang dapat dikendalikan BakoshApp: sajikan empat endpoint HTTP pada port lokal, dan program Anda bereaksi terhadap gift, like, follow, dan chat TikTok dan Kick.

BakoshApp dapat menjalankan aksi di dalam program Anda. Tool Anda menyajikan HTTP API kecil pada port lokal; BakoshApp membaca daftar aksi Anda dan memanggil salah satunya setiap kali event TikTok atau Kick cocok dengan pemicu pengguna. Apa pun yang dapat Anda kendalikan dari kode — lampu pintar, mikrokontroler, soundboard, game lain, bot Anda sendiri — dapat bereaksi terhadap live stream tanpa mod BakoshApp.

Bagaimana semuanya terhubung

  1. Tool Anda mendengarkan di http://127.0.0.1:8833.
  2. Pengguna menghubungkannya di Pengaturan → Third-Party (host dan port) dan memeriksanya dengan Uji koneksi.
  3. Pada tab Aksi milik sebuah mod, pengguna mengklik Tambah baru, memilih pemicu, lalu di Semua Aksi → Eksternal mengonfigurasi Third-Party Action: BakoshApp mengisi dua daftar dengan kategori dan aksi Anda.
  4. Pada setiap event yang cocok, BakoshApp memanggil tool Anda, dan kode Anda yang mengerjakan tugasnya.

Koneksinya satu arah: BakoshApp yang memanggil Anda, tidak pernah sebaliknya.

Port dan alamat

  • 8833 adalah default. Pengguna dapat mengubahnya di Pengaturan → Third-Party; beri tahu pengguna Anda port mana yang harus dimasukkan jika Anda menggunakan port lain.
  • 8832 tidak dapat digunakan: BakoshApp sendiri mendengarkan di situ (begitulah cara TikFinity menemukan BakoshApp), dan pengaturan akan menolaknya.
  • Tidak ada autentikasi. Dengarkan di 127.0.0.1, bukan 0.0.0.0, agar API tidak dapat dijangkau dari jaringan.
  • BakoshApp selalu menggunakan HTTP biasa.

Endpoint

Tool Anda harus menyajikan keempatnya. Setiap respons berupa JSON dengan member data.

1. Info aplikasi

Mengidentifikasi tool Anda. BakoshApp menampilkannya sebagai "Connected with Mock Tool 1.0 by Bakosh" di Pengaturan dan di configurator aksi.

GET /api/app/info
{ "data": { "name": "Mock Tool", "version": "1.0", "author": "Bakosh" } }

2. Kategori

Daftar pertama pada configurator.

GET /api/features/categories
{
  "data": [
    { "categoryId": "smart_device_control", "categoryName": "Control Smart Devices" },
    { "categoryId": "serial_port_control",  "categoryName": "Control Serial Port" }
  ]
}

3. Aksi

Daftar kedua: aksi-aksi dari satu kategori. categoryId di-URL-encode.

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" }
  ]
}

Daftar menampilkan item Anda sesuai urutan Anda mengembalikannya. Aksi yang sudah disimpan pengguna tetapi tidak lagi Anda kembalikan akan tetap berada di bagian atas daftar, sehingga tidak berubah secara diam-diam.

Peringatan

categoryId dan actionId adalah satu-satunya yang disimpan BakoshApp untuk sebuah aksi yang dikonfigurasi. Jaga agar tetap stabil: mengganti nama id akan merusak setup yang sudah ada. Nama hanya untuk tampilan dan dapat berubah kapan saja.

4. Eksekusi

Dipanggil setiap kali event yang cocok menjalankan aksi.

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://…"
  }
}

Jawab dengan array data kosong setelah Anda menerima request:

{ "data": [] }

Timing

  • BakoshApp menunggu hingga 5 detik untuk ketiga endpoint GET dan 10 detik untuk exec. Request yang gagal atau timeout tidak akan diulang.
  • Jika aksi memiliki Jumlah di atas 1, BakoshApp memanggil exec sebanyak itu, satu demi satu: menunggu jawaban Anda, lalu menunggu Interval baris tersebut, baru memanggil lagi.
  • Pemanggilan untuk baris yang sama datang satu per satu; baris yang berbeda dapat memanggil Anda secara paralel.

Jadi jawablah dengan cepat dan lakukan pekerjaan yang lambat di background — penonton dapat mengirim gift lebih cepat daripada pergerakan serial port.

Objek context

context mendeskripsikan event yang menjalankan aksi. Hanya field yang ada untuk event tersebut yang akan muncul — periksa dulu sebelum membacanya.

FieldTipeTersedia
triggerTypeIdnumberselalu — lihat di bawah
eventTypestringselalu — gift, like, chat, follow, share, joined, subscribe, tikfinity, atau test
sourcestringselalu — eulerstream (TikTok), kick, tikfinity, atau test
platformstringevent TikTok dan Kick — tiktok atau kick
usernamestringselalu — handle penonton
nicknamestringevent TikTok dan Kick — nama tampilan
userIdstringevent TikTok dan Kick
profilePictureUrlstringbiasanya (link avatar TikTok kedaluwarsa)
commentstringpesan chat; di Kick juga pesan yang disertakan pada gift
giftNamestringgift
giftIdnumbergift TikTok
repeatCountnumbergift TikTok — gift dalam rentetan; langganan hadiah Kick — jumlah penerima
diamondCountnumbergift — nilai dalam Diamonds (TikTok) atau harga dalam Kicks (Kick)
coinsnumbersama seperti diamondCount
likeCountnumberlike
subMonthnumberlangganan

Event yang diteruskan dari TikFinity hanya membawa triggerTypeId (selalu 0), source, eventType, dan username.

Jenis pemicu

triggerTypeId adalah jenis pemicu yang dikonfigurasi pengguna, sehingga gift yang dipilih berdasarkan nama dan gift yang dicocokkan berdasarkan nilai dapat dibedakan:

IdPemicu
1Bagikan
3Min-Maks (rentang nilai gift)
4Hadiah
6Bergabung
7Like
9Ikuti
10Subscribe / Super Fan
11Obrolan
0TikFinity, atau lainnya

Perlakukan id yang tidak dikenal sebagai 0; lebih banyak id dapat ditambahkan di kemudian hari.

Tombol Uji

Uji pada baris aksi (dan hotkey-nya) memanggil exec dengan data contoh: source dan eventType adalah test, triggerTypeId berasal dari pemicu baris tersebut, penontonnya adalah bakosh_app, dan giftnya adalah Rose (giftId 5655). Tidak ada platform.

Melaporkan masalah

Kembalikan message untuk mendeskripsikan apa yang salah:

{ "message": "Serial port COM3 is not available" }
  • Pada endpoint GET, message apa pun akan membuat BakoshApp menganggap jawabannya sebagai error, meskipun dengan HTTP 200.
  • Pada exec, message ditulis ke console dan file log BakoshApp sebagai warning. Pengguna tidak akan mendapat pop-up.

Status error HTTP juga diperhatikan; tanpa message, log hanya menampilkan kode statusnya.

Bekerja dengan TikFinity juga

Interface ini cocok dengan third-party interface milik TikFinity — empat path dan nama field yang sama — sehingga satu tool dapat melayani keduanya. Port-nya berbeda: TikFinity mencari tool di 8832, yang ditempati BakoshApp selagi berjalan, jadi berikan BakoshApp port lain.

TikFinity adalah web app dan memerlukan header CORS (Access-Control-Allow-Origin: * dan sejenisnya) plus jawaban untuk preflight request OPTIONS. BakoshApp tidak memerlukannya, tetapi mengirimkannya tidak masalah. BakoshApp mengirim lebih banyak field context daripada TikFinity — abaikan yang tidak Anda pakai.

Contoh tool lengkap yang berfungsi

Tanpa dependency — simpan sebagai tool.mjs dan jalankan 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}`));

Menguji tool Anda

  1. Jalankan tool Anda.
  2. Di BakoshApp, buka Pengaturan → Third-Party, periksa host dan port, lalu klik Uji koneksi. Anda akan melihat nama, versi, dan author dari tool Anda.
  3. Pada tab Aksi milik sebuah mod, klik Tambah baru, pilih pemicu, lalu klik Berikutnya. Di Semua Aksi → Eksternal, klik Configure di sebelah Third-Party Action, pilih kategori dan aksi Anda, lalu simpan.
  4. Klik Uji pada baris baru — tool Anda menerima exec dengan eventType: "test".
  5. Mulai live dan periksa apakah event sungguhan masuk.

Jika configurator menampilkan "Tidak dapat terhubung! Periksa integrasimu.", periksa apakah tool mendengarkan di 127.0.0.1, apakah port-nya cocok dengan Pengaturan, dan apakah GET /api/app/info mengembalikan jawabannya di dalam data.