Third-Party Interface

Bina alat yang boleh dikawal oleh BakoshApp: sediakan empat titik akhir HTTP pada port setempat, dan program anda bertindak balas kepada hadiah, like, ikutan dan sembang TikTok dan Kick.

BakoshApp boleh menjalankan tindakan di dalam program anda. Alat anda menyediakan API HTTP kecil pada port setempat; BakoshApp membaca senarai tindakan anda dan memanggil satu apabila acara TikTok atau Kick menepati pencetus pengguna. Apa sahaja yang boleh anda kawal melalui kod — lampu pintar, mikropengawal, papan bunyi, permainan lain, bot anda sendiri — boleh bertindak balas kepada siaran langsung tanpa mod BakoshApp.

Cara semuanya berfungsi bersama

  1. Alat anda mendengar pada http://127.0.0.1:8833.
  2. Pengguna menyambungkannya dalam Tetapan → Third-Party (hos dan port) dan menyemaknya dengan Uji sambungan.
  3. Pada tab Tindakan sesuatu mod, pengguna mengklik Tambah baharu, memilih pencetus, dan dalam Semua Tindakan → Luaran mengkonfigurasi Third-Party Action: BakoshApp mengisi dua senarai dengan kategori dan tindakan anda.
  4. Pada setiap acara yang sepadan, BakoshApp memanggil alat anda, dan kod anda melakukan kerjanya.

Sambungan ini adalah sehala: BakoshApp memanggil anda, tidak pernah sebaliknya.

Port dan alamat

  • 8833 ialah port lalai. Pengguna boleh menukarnya dalam Tetapan → Third-Party; beritahu pengguna anda port mana untuk dimasukkan jika anda menggunakan port lain.
  • 8832 tidak boleh digunakan: BakoshApp sendiri mendengar di situ (itulah cara TikFinity mencari BakoshApp), dan tetapan tersebut akan menolaknya.
  • Tiada pengesahan. Dengar pada 127.0.0.1, bukan 0.0.0.0, supaya API tidak boleh dicapai daripada rangkaian.
  • BakoshApp sentiasa menggunakan HTTP biasa.

Titik akhir

Alat anda mesti menyediakan keempat-empatnya. Setiap respons ialah JSON dengan ahli data.

1. Maklumat aplikasi

Mengenal pasti alat anda. BakoshApp memaparkannya sebagai "Connected with Mock Tool 1.0 by Bakosh" dalam Tetapan dan dalam pengkonfigurasi tindakan.

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

2. Kategori

Senarai pertama dalam pengkonfigurasi.

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

3. Tindakan

Senarai kedua: tindakan bagi satu kategori. categoryId dikodkan 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" }
  ]
}

Senarai memaparkan item anda mengikut susunan yang anda pulangkan. Tindakan yang telah disimpan oleh pengguna tetapi tidak lagi anda pulangkan kekal di bahagian atas senarai, supaya ia tidak berubah secara senyap.

Amaran

categoryId dan actionId adalah satu-satunya yang disimpan BakoshApp bagi tindakan yang dikonfigurasi. Pastikan kedua-duanya stabil: menukar nama id akan merosakkan persediaan sedia ada. Nama hanya untuk paparan dan boleh berubah pada bila-bila masa.

4. Laksana

Dipanggil setiap kali acara yang sepadan menjalankan tindakan.

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 tatasusunan data kosong sebaik sahaja anda menerima permintaan:

{ "data": [] }

Masa

  • BakoshApp menunggu sehingga 5 saat untuk tiga titik akhir GET dan 10 saat untuk exec. Permintaan yang gagal atau tamat masa tidak akan diulang.
  • Jika tindakan mempunyai Kiraan melebihi 1, BakoshApp memanggil exec sebanyak itu, satu demi satu: ia menunggu jawapan anda, kemudian menunggu Selang masa baris itu, kemudian memanggil semula.
  • Panggilan bagi baris yang sama datang satu demi satu; baris yang berlainan boleh memanggil anda secara selari.

Jadi jawab dengan cepat dan lakukan kerja yang perlahan di latar belakang — penonton boleh menghantar hadiah lebih pantas daripada pergerakan port bersiri.

Objek context

context menerangkan acara yang menjalankan tindakan. Hanya medan yang wujud untuk acara tersebut akan hadir — semak dahulu sebelum anda membacanya.

MedanJenisHadir
triggerTypeIdnumbersentiasa — lihat di bawah
eventTypestringsentiasa — gift, like, chat, follow, share, joined, subscribe, tikfinity atau test
sourcestringsentiasa — eulerstream (TikTok), kick, tikfinity atau test
platformstringAcara TikTok dan Kick — tiktok atau kick
usernamestringsentiasa — handle penonton
nicknamestringAcara TikTok dan Kick — nama paparan
userIdstringAcara TikTok dan Kick
profilePictureUrlstringbiasanya (pautan avatar TikTok luput)
commentstringmesej sembang; pada Kick juga mesej yang dilampirkan pada hadiah
giftNamestringhadiah
giftIdnumberHadiah TikTok
repeatCountnumberHadiah TikTok — bilangan hadiah dalam rentetan; langganan hadiah Kick — bilangan penerima
diamondCountnumberhadiah — nilai dalam Diamonds (TikTok) atau harga dalam Kicks (Kick)
coinsnumbersama seperti diamondCount
likeCountnumberlike
subMonthnumberlangganan

Acara yang dihantar semula daripada TikFinity hanya membawa triggerTypeId (sentiasa 0), source, eventType dan username.

Jenis pencetus

triggerTypeId ialah jenis pencetus yang dikonfigurasikan oleh pengguna, supaya hadiah yang dipilih mengikut nama dan hadiah yang dipadankan mengikut nilai dapat dibezakan:

IdPencetus
1Kongsi
3Min-Max (julat nilai hadiah)
4Hadiah
6Menyertai
7Like
9Ikut
10Subscribe / Super Fan
11Sembang
0TikFinity, atau apa-apa sahaja yang lain

Layan id yang tidak diketahui sebagai 0; lebih banyak mungkin akan ditambah.

Butang Uji

Uji pada baris tindakan (dan kekunci pintasannya) memanggil exec dengan data contoh: source dan eventType ialah test, triggerTypeId datang daripada pencetus baris itu, penonton ialah bakosh_app, dan hadiahnya ialah Rose (giftId 5655). Tiada platform.

Melaporkan masalah

Pulangkan message untuk menerangkan apa yang tidak kena:

{ "message": "Serial port COM3 is not available" }
  • Pada titik akhir GET, sebarang message menyebabkan BakoshApp menganggap jawapan itu sebagai ralat, walaupun dengan HTTP 200.
  • Pada exec, message ditulis ke konsol dan fail log BakoshApp sebagai amaran. Pengguna tidak menerima pop-up.

Status ralat HTTP turut dihormati; tanpa message, log hanya memaparkan kod status.

Turut berfungsi dengan TikFinity

Interface ini sepadan dengan interface pihak ketiga TikFinity — laluan dan nama medan yang sama — jadi satu alat boleh melayan kedua-duanya. Port yang berbeza: TikFinity mencari alat pada 8832, yang diduduki oleh BakoshApp semasa ia berjalan, jadi berikan BakoshApp port yang lain.

TikFinity ialah aplikasi web dan memerlukan header CORS (Access-Control-Allow-Origin: * dan sebagainya) serta jawapan kepada permintaan preflight OPTIONS. BakoshApp tidak memerlukannya, tetapi menghantarnya tidak membawa mudarat. BakoshApp menghantar lebih banyak medan context berbanding TikFinity — abaikan yang anda tidak gunakan.

Alat lengkap yang berfungsi

Tiada kebergantungan — 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 alat anda

  1. Mulakan alat anda.
  2. Dalam BakoshApp, buka Tetapan → Third-Party, semak hos dan port, dan klik Uji sambungan. Anda sepatutnya melihat nama, versi dan pencipta alat anda.
  3. Pada tab Tindakan sesuatu mod, klik Tambah baharu, pilih pencetus dan klik Seterusnya. Dalam Semua Tindakan → Luaran, klik Configure di sebelah Third-Party Action, pilih kategori dan tindakan anda, dan simpan.
  4. Klik Uji pada baris baharu — alat anda menerima exec dengan eventType: "test".
  5. Siar langsung dan semak bahawa acara sebenar tiba.

Jika pengkonfigurasi memaparkan "Tidak dapat menyambung! Semak integrasi anda.", semak bahawa alat itu mendengar pada 127.0.0.1, bahawa port itu sepadan dengan Tetapan, dan bahawa GET /api/app/info memulangkan jawapannya di dalam data.