Kreator widgetów: dokumentacja techniczna
Ta strona opisuje, czego Twój kod może używać w widgecie z kreatora widgetów KickBot: zdarzeń widgetEvent, obiektu globalValues, obiektu userVariables i funkcji pomocniczych window.kickbotWidget. Każdy widget to zwykły HTML, CSS i JavaScript, który działa w OBS jako browser source. KickBot łączy się z Kick za Ciebie i przekazuje zdarzenia do Twojego kodu.
Jak działa widget
Dział zatytułowany „Jak działa widget”Gdy OBS otwiera URL widgetu, KickBot:
- Wczytuje stronę widgetu z przezroczystym tłem.
- Dodaje Twój CSS w elemencie
<style>i wstawia Twój HTML na stronę. - Wczytuje dane Twojego kanału z Kick (liczbę obserwujących, liczbę widzów, stan streama i ostatnie wiadomości z czatu) do
globalValues. - Uruchamia Twój JavaScript. Działa on raz, po kroku 3, więc
globalValuesjest gotowy, gdy Twój kod startuje. - Wysyła do Twojego kodu zdarzenia na żywo jako zdarzenia
widgetEventnadocument.
Twój JavaScript może czytać dwa obiekty bez żadnego importu: globalValues i userVariables. Funkcje pomocnicze są w window.kickbotWidget.
Limity:
| Element | Limit |
|---|---|
| Szerokość i wysokość | Ustawiasz w sekcji Ustawienia podstawowe. Nowy pusty widget ma 800 × 600. Okienko Nowy widget przyjmuje do 7680 × 4320. |
| HTML, CSS i JavaScript | Do 2 000 000 znaków na plik |
| Nazwa widgetu | Do 500 znaków |
| Pliki dla zmiennych użytkownika | Do 25 MB na plik |
| Widgety z kreatora w planie Darmowym | 10 (bez limitu w Premium) |
Nasłuchuj zdarzeń
Dział zatytułowany „Nasłuchuj zdarzeń”Dodaj jeden listener widgetEvent na document. Każde zdarzenie ma event.detail z trzema polami:
| Pole | Typ | Wartość |
|---|---|---|
event_name | string | Zdarzenie, np. followEvent |
source | string | Zawsze kick |
data | object | Dane zdarzenia (zobacz niżej) |
document.addEventListener('widgetEvent', (event) => { const { event_name, data } = event.detail;
if (event_name === 'followEvent') { showAlert(data.user.username + ' followed!'); } if (event_name === 'subEvent') { showAlert(data.username + ' subscribed for ' + data.months + ' months'); }});Lista zdarzeń
Dział zatytułowany „Lista zdarzeń”| Nazwa zdarzenia | Kiedy się pojawia | Przycisk testowy |
|---|---|---|
subEvent | Widz subuje kanał | Sub |
subGiftEvent | Widz podarowuje suby | Sub w prezencie |
kicksEvent | Widz wysyła KICKi | KICKs |
followEvent | Widz zaczyna obserwować | Follow |
unfollowEvent | Widz przestaje obserwować | Unfollow |
chatMessageEvent | Ktoś wysyła wiadomość na czacie | Wiadomość |
chatMessageDeletedEvent | Moderator usuwa wiadomość | Wiadomość usunięta |
chatMessagePinnedEvent | Wiadomość zostaje przypięta | Wiadomość przypięta |
chatMessageUnpinnedEvent | Przypięta wiadomość zostaje usunięta | Wiadomość odpięta |
chatClearedEvent | Moderator czyści czat | Czat wyczyszczony |
followerCountUpdatedEvent | Kick wysyła nową liczbę obserwujących | Aktualizacja liczby followerów |
subCountUpdatedEvent | Liczba subów na Kick się zmieniła | Aktualizacja liczby subów |
viewerCountUpdatedEvent | Kick wysyła nową liczbę widzów | Aktualizacja liczby widzów |
raidEvent | Inny kanał robi na Ciebie raid (hostuje Cię) | Raid |
streamOnline | Twój stream się zaczyna | Stream online |
streamOffline | Twój stream się kończy | Stream offline |
Nie ma zdarzenia napiwku. Do alertów o napiwkach użyj widgetu alertów napiwków.
Dane zdarzeń
Dział zatytułowany „Dane zdarzeń”To są dane w event.detail.data. Odpowiadają zdarzeniom testowym w edytorze. Prawdziwe zdarzenia mogą mieć więcej pól. Nazwy, liczby i ID poniżej to przykłady.
subEvent
{ months: 1, username: 'viewer_one', chatroom_id: 3847194}subGiftEvent
{ chatroom_id: 3847194, gifted_usernames: ['viewer_one', 'viewer_two', 'viewer_three'], gifter_username: 'big_gifter'}kicksEvent
{ message: 'Great stream!', sender: { id: 12345678, username: 'viewer_one', username_color: '#93EBE0' }, gift: { gift_id: 'full_send', name: 'Full Send', amount: 100, type: 'BASIC', tier: 'BASIC', character_limit: 0, pinned_time: 0 }, channel: 'channel_3984507'}followEvent i unfollowEvent (ten sam format; followers_count to nowa liczba)
{ id: 'd4e5f6a7-89b0-12c3-d456-78901e2f3a4b', channel: { id: 3984507, slug: 'kickbotdev' }, user: { id: 14873539, slug: 'viewer_one', username: 'viewer_one' }, followers_count: 36, created_at: '2024-05-13T22:19:07+00:00'}chatMessageEvent
{ id: '85c884b3-7377-478c-b6aa-22b7db752b93', chatroom_id: 3974112, content: 'hello [emote:37226:KEKW]', type: 'message', created_at: '2024-05-13T22:29:52+00:00', sender: { id: 4063326, username: 'viewer_one', slug: 'viewer_one', identity: { color: '#72ACED', badges: [{ type: 'subscriber', text: 'Subscriber', count: 3 }] } }}Emotki z Kick są w content jako [emote:ID:NAME]. Użyj createChatMessageFragment (zobacz Bezpieczne wyświetlanie tekstu z czatu), żeby zamienić je na obrazki.
chatMessageDeletedEvent
{ id: '9cd3788a-ecd2-4051-a162-a7ea9be8ce7a', message: { id: '89d6be86-63db-4581-922e-14a6c4a9c2e6' }}Użyj data.message.id, żeby znaleźć i usunąć wyświetloną wiadomość.
chatMessagePinnedEvent (data.message ma ten sam format co dane chatMessageEvent)
{ message: { id: '5d798a38-ad17-45e4-8169-bda2faa85b79', chatroom_id: 3974112, content: 'This is a pinned message!', type: 'message', created_at: '2024-05-13T22:30:41+00:00', sender: { id: 4063326, username: 'kickbotdev', slug: 'kickbotdev', identity: { color: '#72ACED', badges: [] } } }}chatMessageUnpinnedEvent: data to pusta tablica ([]).
chatClearedEvent
{ id: '47e3596f-0274-46e0-85b1-029fa3bfc5ea' }followerCountUpdatedEvent (uwaga: followersCount jest w camelCase)
{ followersCount: 1532, channel_id: 4599, created_at: 1715639984 }subCountUpdatedEvent
{ subscriber_count: 184, channel_id: 4599 }viewerCountUpdatedEvent
{ viewer_count: 320, channel_id: 5937485 }raidEvent
{ chatroom_id: 839485, optional_message: 'gg stream', number_viewers: 150, host_username: 'raiding_channel'}streamOnline
{ livestream: { id: 3984507, channel_id: 3984507, session_title: 'Test stream!', created_at: '2024-05-13T22:30:41+00:00' }}streamOffline
{ livestream: { id: 3984507, channel: { id: 3984507, is_banned: false } }}Wartości globalne
Dział zatytułowany „Wartości globalne”globalValues przechowuje bieżący stan Twojego kanału. KickBot wypełnia go, zanim uruchomi się Twój kod, i aktualizuje go, gdy przychodzą zdarzenia. Użyj go, żeby narysować widget od razu na starcie, zanim przyjdzie jakiekolwiek zdarzenie.
globalValues = { subCount: 184, followerCount: 1532, viewerCount: 320, lastFollower: { /* the last follow */ }, lastSub: { /* the last sub, for example { username, months } */ }, lastGiftedSub: { /* the last gift, for example { gifter_username, gifted_usernames } */ }, chatMessages: [ /* chatMessageEvent payloads */ ], streamerInfo: { kick: { username: 'KickBotDev', slug: 'kickbotdev', profile_picture: 'https://files.kick.com/images/user/.../fullsize.webp', user_id: '4063326', channel_id: '3984507', chatroom_id: '3974112', bio: 'Channel bio', subscriber_badges: [ /* your channel's sub badges from Kick */ ] } }, currentStream: { is_live: true, title: 'Stream title', started_at: '2026-10-24 18:00:00' }}| Wartość | Jak się aktualizuje |
|---|---|
subCount | Wczytana z Kick. Rośnie o 1 przy każdym subEvent i o 1 przy każdym podarowanym subie, a subCountUpdatedEvent ustawia ją na nowo. |
followerCount | Wczytana z Kick. Ustawiają ją followEvent, unfollowEvent i followerCountUpdatedEvent. |
viewerCount | Wczytana z Kick (0, gdy jesteś offline). Ustawia ją viewerCountUpdatedEvent. |
lastFollower, lastSub, lastGiftedSub | Ostatni taki przypadek, który KickBot widział na Twoim kanale, albo null. Aktualizuje je odpowiednie zdarzenie. |
chatMessages | Ostatnie wiadomości z czatu Kick przy wczytaniu widgetu, potem każda nowa wiadomość. Trzyma 100 najnowszych. chatClearedEvent ją opróżnia. Żeby ukrywać usunięte wiadomości, obsłuż chatMessageDeletedEvent we własnym kodzie. |
streamerInfo.kick | Twój profil Kick. Nie zmienia się, gdy widget działa. |
currentStream | Wczytana z Kick przy wczytaniu widgetu. streamOnline ani streamOffline jej nie aktualizują. Jeśli potrzebujesz aktualnego stanu, nasłuchuj tych zdarzeń. |
Zmienne użytkownika
Dział zatytułowany „Zmienne użytkownika”Zmienne użytkownika to ustawienia, które streamerzy widzą, gdy otwierają Twój widget w Zapisanych widgetach. Dodajesz je w sekcji Zmienne użytkownika w edytorze. W kodzie odczytujesz wartość przez userVariables.<variable name>.value.
const goal = Number(userVariables.follower_goal.value);document.body.style.color = userVariables.text_color.value;Pola zmiennej:
| Pole | Co to jest |
|---|---|
| Tytuł | Etykieta, którą widzą streamerzy. |
| Nazwa zmiennej | Nazwa w Twoim kodzie. Tylko litery, cyfry i _. Po utworzeniu zmiennej nie można jej zmienić. |
| Tooltip | Dodatkowy tekst pomocy pod tytułem. |
| Typ zmiennej | Zobacz tabelę poniżej. |
| Wartość domyślna | Wartość, zanim streamer ją zmieni. Może być pusta. |
| Wymagana | Streamer musi wpisać wartość, zanim zapisze. |
| Typ | Co widzi streamer | value w Twoim kodzie |
|---|---|---|
| Tekst | Pole tekstowe | String |
| Liczba | Pole liczbowe | Liczba albo string z liczbą. Dla pewności użyj Number(). |
| Kolor | Wybór koloru | String z kolorem hex, np. #ffffff |
| Lista rozwijana | Menu z Twoimi opcjami | Wybrana opcja jako string. Domyślnie pierwsza opcja. |
| Przełącznik | Przełącznik wł./wył. | true albo false |
| Obraz/GIF | Pole na URL i przycisk wgrywania | URL do pliku |
| Wideo | Pole na URL i przycisk wgrywania | URL do pliku |
| Audio | Pole na URL i przycisk wgrywania | URL do pliku |
Wgrane pliki przechowuje KickBot, a value to URL pliku. Menu obok zmiennej pozwala przenieść ją w górę lub w dół, edytować ją albo usunąć. Kolejność w edytorze to kolejność, którą widzą streamerzy.
Bezpieczne wyświetlanie tekstu z czatu
Dział zatytułowany „Bezpieczne wyświetlanie tekstu z czatu”Traktuj każde pole zdarzenia i każdą zmienną użytkownika jak tekst od obcej osoby. KickBot czyści tekst z czatu i ze zdarzeń, zanim dostanie go Twój kod, więc jest bezpieczny jako tekst w HTML, ale nie jako URL, CSS czy skrypt. Nie wstawiaj surowych pól zdarzeń do innerHTML. Użyj tych funkcji pomocniczych:
| Funkcja | Co robi |
|---|---|
window.kickbotWidget.createChatMessageFragment(content, font_size) | Zwraca DocumentFragment z węzłami tekstowymi i obrazkami emotek z Kick. Emotki mają font_size + 3 pikseli. Domyślnie font_size to 20. |
window.kickbotWidget.createTextNode(value) | Zwraca węzeł tekstowy dla dowolnej wartości. |
window.kickbotWidget.escapeHtmlText(value) | Escapuje tekst do użycia między tagami HTML, gdy musisz zbudować string z HTML. Nie używaj go do URL-i, CSS ani skryptów. |
document.addEventListener('widgetEvent', (event) => { if (event.detail.event_name !== 'chatMessageEvent') return; const data = event.detail.data;
const line = document.createElement('div'); line.id = 'msg-' + data.id; const name = document.createElement('strong'); name.style.color = data.sender.identity.color; name.append(window.kickbotWidget.createTextNode(data.sender.username + ': ')); line.append(name); line.append(window.kickbotWidget.createChatMessageFragment(data.content, 20)); document.getElementById('chat').append(line);});Do innego tekstu używaj textContent albo createTextNode.
Podgląd
Dział zatytułowany „Podgląd”Podgląd w edytorze działa jak OBS, z kilkoma różnicami ułatwiającymi testy:
- Gdy zmienisz kod albo zmienną użytkownika, podgląd uruchamia Twój JavaScript ponownie. KickBot najpierw usuwa listenery
widgetEventz poprzedniego uruchomienia. Timery zsetIntervalisetTimeoutnie są usuwane, więc kliknij przycisk odświeżania, jeśli zaczną się nawarstwiać. - Gdy zmienisz szerokość albo wysokość, podgląd się przeładowuje.
- Zdarzenia testowe trafiają tylko do podglądu. Testowy Follow dodaje 1 do
globalValues.followerCount, a Unfollow odejmuje 1. Aktualizacja liczby widzów wysyła przykładową liczbę. Wiadomość usunięta usuwa losową wiadomość z czatu w podglądzie. - Jeśli Twój kanał nie ma jeszcze ostatniego obserwującego, suba ani podarowanego suba, podgląd używa przykładowych danych dla
lastFollower,lastSubilastGiftedSub. - Żeby zobaczyć wynik
console.logi błędy, kliknij przycisk otwierania w nowym oknie i otwórz w tym oknie narzędzia deweloperskie.
Przykład: cel obserwujących
Dział zatytułowany „Przykład: cel obserwujących”To krótki cel obserwujących. Używa listenera zdarzeń, globalValues i dwóch zmiennych użytkownika: follower_goal (Liczba) i bar_color (Kolor).
HTML:
<div class="goal"> <span id="count"></span> / <span id="target"></span> <div class="bar"><div class="fill"></div></div></div>CSS:
body { margin: 0; font-family: Arial, sans-serif; color: #fff; }.goal { padding: 12px; background: #100c28; border-radius: 16px; font-size: 32px; font-weight: bold; }.bar { height: 24px; margin-top: 8px; background: #3d3957; border-radius: 12px; overflow: hidden; }.fill { height: 100%; width: 0; transition: width 0.3s ease; }JavaScript:
const target = Number(userVariables.follower_goal.value) || 100;document.getElementById('target').textContent = target;document.querySelector('.fill').style.background = userVariables.bar_color.value;
function update(count) { document.getElementById('count').textContent = count; document.querySelector('.fill').style.width = Math.min((count / target) * 100, 100) + '%';}
document.addEventListener('widgetEvent', (event) => { const { event_name, data } = event.detail; if (event_name === 'followEvent' || event_name === 'unfollowEvent') update(data.followers_count); if (event_name === 'followerCountUpdatedEvent') update(data.followersCount);});
update(globalValues.followerCount);Pełną wersję z większą liczbą ustawień dostaniesz, gdy zaczniesz nowy widget od szablonu Simple Follower Goal.
Wskazówki
Dział zatytułowany „Wskazówki”- Narysuj stan początkowy z
globalValues, a potem zmieniaj go przy zdarzeniach. Widget, który czeka na zdarzenie, jest pusty, dopóki coś się nie wydarzy. - Zapisane widgety pokazują przyciski testowe tylko dla nazw zdarzeń, które występują w Twoim JavaScripcie. Wpisz w kodzie pełną nazwę zdarzenia (np.
'followEvent'), żeby streamerzy mogli przetestować Twój widget. - Zostaw przezroczyste tło, chyba że tło jest częścią projektu. Dzięki przezroczystemu tłu widget leży na wierzchu sceny.
- Widgetami z kreatora możesz też zarządzać przez API KickBot. Zobacz dokumentację API widgetów.