System Event Flow

Przewodnik po edytorze Event Flow

Twórz niezawodne automatyzacje w Social Stream Ninja. Ten przewodnik omawia podstawy, węzły logiczne, przepływ sygnałów oraz praktyczne zagadnienia, o które twórcy pytają najczęściej (np. unikanie echa czatu i dobór układów AND/NOT).

Polski

0. Szybkie wprowadzenie

Event Flow to edytor oparty na węzłach. Każda linia przenosi dane wiadomości i stan logiczny (true = kontynuuj, false = zatrzymaj). Użyj źródeł do wprowadzania zdarzeń, węzłów logicznych do podejmowania decyzji o filtrowaniu oraz akcji do wykonywania działań (wysyłania czatu, sterowania nakładkami, przekazywania wiadomości itd.).
Chcesz zapamiętać uczestników, później sprawdzić uprawnienia do udziału, przeprowadzić losowanie unikalnych użytkowników lub wyczyścić jedną nazwaną listę? Otwórz Przewodnik po User Memory z opisem modelu wspólnego stanu, zrzutami ekranu i przykładem do importu.

Czym jest ten edytor?

Edytor Event Flow jest warstwą zaawansowanej automatyzacji Social Stream Ninja. Uzupełnia proste przełączniki okna popup i pozwala tworzyć własną logikę routingu. Użyj go, gdy chcesz:

  • Przekazuj czat między usługami z użyciem filtrów (np. kopiuj Twitch do Discorda, ale blokuj komendy).
  • Twórz komendy zależne od lojalności, gry ze słowami kluczowymi lub warunki udziału w losowaniu przy użyciu logiki AND/OR/NOT.
  • Uruchamiaj własne nakładki, dźwięki, sceny OBS lub webhooki na podstawie danych uzupełnianych w przepływie.
  • Łącz wiele platform w jednej automatyzacji (Kick + Twitch + YouTube obsługiwane przez jeden przepływ).

Okno popup zapewnia szybkie ustawienia, a Event Flow — narzędzia do tworzenia własnych przepływów.

Uruchomienie i podstawy

  • Otwórz edytor Event Flow z menu głównego panelu (w aplikacji desktopowej lub rozszerzeniu).
  • Każdy projekt jest zapisywany lokalnie do czasu eksportu. Użyj Export aby utworzyć kopię zapasową lub udostępnić.
  • Pracuj na obszarach roboczych nazywanych przepływami. Każdy przepływ może jednocześnie subskrybować wiele platform.

Węzły w skrócie

  • Wejścia (porty po lewej) oczekują kontekstu wiadomości.
  • Wyjścia (porty po prawej) emitują ten sam kontekst wraz ze zmianami.
  • Węzły logiczne mogą wysyłać sygnały zarówno przez kanał true jak i przez opcjonalny kanał false .

Struktura danych zdarzenia

Każda wiadomość przenosi obiekt JSON. Obowiązkowe klucze są zgodne z docs/event-reference.html (platform, type, chatname, chatmessage itd.). Własne dane dodawaj w meta.

Każdy przepływ zaczyna się od wyzwalacza

Węzły akcji (zielone) nigdy nie uruchamiają się samodzielnie — wykonują się tylko wtedy, gdy poprzedzający je węzeł wyzwalacza (niebieski) zwróci true. Przepływ złożony wyłącznie z połączonych akcji wygląda poprawnie, ale pozostaje bezczynny, ponieważ nic nie uruchamia łańcucha. Nazwy węzłów opisują, co węzeł robi, a nie moment wykonania: Wyróżnij wiadomość (Feature Message) wyróżnia wiadomość, gdy przepływ dotrze do tego węzła — nie uruchamia się, gdy wyróżnisz wiadomość gdzie indziej.

Dwa węzły akcji połączone w łańcuch bez węzła wyzwalacza
❌ Nigdy się nie uruchamia. Feature Message i Speak Text to węzły akcji; bez wyzwalacza na początku nic nie uruchamia łańcucha.
Wyzwalacz Any Message połączony z akcjami Feature Message i Speak Text
✅ Działa. Wyzwalacz Dowolna wiadomość rozpoczyna łańcuch (może to być też Message Contains, wyrażenie regularne, zdarzenie wpłaty itd.); obie akcje wykonują się następnie dla każdej pasującej wiadomości.

Nakładka Flow Actions (wyjście akcji)

Zacznij od szablonu alertu:

Wybierz Wpłata: świętowanie + głos aby użyć gotowej animacji i syntetycznego klipu z podziękowaniem, lub zaawansowanego szablonu Wpłata: animacja + dźwięk + filtr OBS . Nowe szablony alertów są początkowo wyłączone, aby można je było najpierw skonfigurować i przetestować. W szablonie OBS wybierz źródło i ten sam domyślnie wyłączony filtr w obu akcjach filtrów.

Odtwórz klip dźwiękowy i Multi-Alerts korzystają teraz ze wspólnej biblioteki 17 dźwięków: oklasków, werbla, świstu, kasy fiskalnej i innych efektów, czterech opisanych syntetycznych fraz po angielsku oraz prostych dźwięków. Nasłuchuj / Zatrzymaj odtwarza podgląd lokalnie i pokazuje stan odtwarzania. Nadal możesz przesłać nagranie lub wybrać plik lokalny aplikacji. W przypadku zmiennych nazw i wiadomości użyj istniejącej akcji Odczytaj tekst (Speak Text) .

Event Flow odtwarza przez źródło przeglądarkowe Flow Actions ; Multi-Alerts odtwarza przez własne źródło przeglądarkowe. Dla tego samego zdarzenia włącz dźwięk tylko w jednym z nich, aby uniknąć podwójnego odtwarzania. Przejdź klawiszem Tab do węzła przepływu i naciśnij Enter lub spację, aby edytować jego właściwości.

Węzły takie jak Odtwórz klip dźwiękowy, Wyświetl nakładkę multimedialną oraz sterowanie OBS potrzebują powierzchni renderowania. Zapewnia ją strona nakładki Flow Actions dostępna pod adresem actions.html. Pozostaw ją uruchomioną w programie do transmisji (OBS, doki przeglądarkowe Streamer.bot itd.), aby akcje Event Flow miały gdzie się wyświetlać.

Wyzwalacz Any Message połączony z akcją Play Audio Clip
Ten przepływ jest kompletny i uruchamia się dla każdej wiadomości — ale dźwięk jest odtwarzany na stronie nakładki Flow Actions, a nie w edytorze. Przycisk Preview w edytorze odtwarza lokalnie; odtwarzanie na żywo wymaga otwartej nakładki. Jeśli przeglądarka blokuje automatyczne odtwarzanie, kliknij Włącz dźwięk na stronie Flow Actions, aby ponowić ostatni zablokowany klip. Kliknięcie w innym miejscu tej strony również włącza odtwarzanie. Źródło przeglądarkowe OBS zwykle pozwala na automatyczne odtwarzanie.
Jak ją otworzyć (z okna popup/panelu):
  1. Otwórz główne okno popup Social Stream Ninja (okno ładowane z popup.html lub ikony rozszerzenia).
  2. Przewiń do karty „Flow Actions”. Użyj przycisku [kopiuj łącze] lub kliknij adres URL na karcie.
  3. Łącze wygląda tak: https://socialstream.ninja/actions.html?session=YOURSESSION. Wklej go jako źródło przeglądarkowe OBS (zalecane 1920×1080) lub otwórz w dowolnej przeglądarce nakładek.
Używanie lokalnych multimediów w samodzielnej aplikacji:
  1. W akcji Play Audio Clip lub Display Media Overlay kliknij Wybierz plik lokalny.
  2. Kliknij Kopiuj lokalny URL Flow Actions dla OBS i użyj wygenerowanego adresu localhost zamiast hostowanego adresu Flow Actions.
  3. Pozostaw SSApp uruchomione. Jeśli wybrany plik zostanie przeniesiony, wróć do akcji i kliknij Połącz ponownie.

Samo rozszerzenie Chrome nie może udostępniać plików z dysku. Jeśli aplikacja desktopowa nie jest dostępna, użyj Upload lub hostowanego adresu URL. Zobacz Przewodnik po plikach multimedialnych dla Event Flow zawierający pełną konfigurację.

Po załadowaniu ta nakładka może:

  • Wyświetlać GIPHY lub multimedia z bezpośrednich adresów URL, tekst i konfetti uruchamiane przez przepływy.
  • Odtwarzać dźwięki (TTS, klipy audio) lokalnie, aby widzowie je słyszeli.
  • Komunikować się z OBS przez ustawienia WebSocket w sekcji Flow Actions okna popup (przełączanie scen, przełączanie źródeł, aktualizacje tekstu GDI+/FreeType, bufor powtórek itd.).
Tryby sterowania OBS:
  • API źródła przeglądarkowego: dostępne tylko wtedy, gdy actions.html działa wewnątrz źródła przeglądarkowego OBS z włączoną opcją Zaawansowany poziom dostępu. Przełączanie scen działa w tym trybie, a akcje nagrywania, transmisji i bufora powtórek mogą używać go awaryjnie.
  • OBS WebSocket: zalecany dla spójnego sterowania. Flow Actions w Social Stream Ninja używa API OBS WebSocket v5 z OBS 28+ i oczekuje współczesnego zestawu żądań na porcie 4455.
  • Hasło: opcjonalne. Dodaj &obspw=... do adresu URL Flow Actions tylko wtedy, gdy serwer OBS wymaga uwierzytelniania.
  • Diagnostyka nakładki: dodaj &obsdebug=1 do adresu URL strony actions.html jeśli podczas rozwiązywania problemów chcesz widzieć na nakładce mały wskaźnik bieżącego połączenia z OBS.
  • Ustaw źródło tekstowe: bezpośrednio aktualizuje wejścia OBS Text (GDI+) i Text (FreeType 2) oraz obsługuje zmienne szablonów Event Flow, takie jak {counterValue} i {counterTarget}.
  • Starsze instalacje 4.x: jeśli nadal używasz obs-websocket 4.x / portu 4444— akcje źródeł, filtrów, wyciszania i tekstu nie będą działać, dopóki nie zaktualizujesz OBS / obs-websocket.

Zobacz osobny Przewodnik po sterowaniu OBS opisujący wszystkie wyzwalacze, akcje, kroki konfiguracji i sprawdzone przykłady.

Zalecana ścieżka diagnostyki:
  1. Otwórz obs-websocket-test.html.
  2. Sprawdź, czy GetVersion, GetCurrentProgramScene i GetSceneList zakończą się powodzeniem.
  3. Uruchom tam test odpowiedniej akcji, zanim sprawdzisz całą automatyzację Event Flow.
Pozostaw nakładkę otwartą. Zamknięcie strony Flow Actions wstrzymuje wszystkie akcje nakładek, dźwięku i OBS w Event Flow. Ukryj ją lub przenieś na drugi monitor zamiast zamykać.

1. Co przechodzi przez węzeł?

Środowisko wykonawcze Event Flow przesyła przez każdy przewód dwie rzeczy:

  1. Dane zdarzenia – obiekt danych zdarzenia lub wiadomości.
  2. Sygnał warunku – true/false bit informujący następny węzeł, czy ma się wykonać.
Jeśli węzeł zwraca false: kolejne węzły przestają się wykonywać, chyba że otrzymają dane osobną gałęzią (np. przez false port w węźle Condition). Ułatwia to tworzenie logiki alternatywnej bez powielania całych przepływów.

Oczekiwane dane wejściowe

  • Źródła zdarzeń (Twitch Message, Timers, Manual Trigger itd.) ignorują dane wejściowe z wcześniejszych węzłów — generują własne dane zdarzenia i zawsze emitują true chyba że sam węzeł zgłosi błąd.
  • Węzły przekształceń i logiki odczytują dane zdarzenia i mogą zmieniać pola, ustawiać stan lub przełączać sygnał warunku na false.
  • Węzły akcji uruchamiają się tylko wtedy, gdy sygnał warunku pozostaje true. Nadal mogą zwracać zaktualizowane dane, jeśli chcesz łączyć kolejne akcje.

Sposoby zwracania danych

Jedno wyjście

Większość węzłów ma jedno wyjście. Dane wejściowe (dane zdarzenia + sygnał warunku) wychodzą bez zmian, chyba że węzeł je modyfikuje.

Wyjścia True/False

Węzły Condition, Compare, Regex i Logic udostępniają dwa porty wyjściowe. True przechodzi przez zielony port; false staje się dostępne na szarym/czerwonym porcie.

Przekazywanie a nadpisywanie

Niektóre węzły (Set Variable, Math, Text Replace) zmieniają dane zdarzenia, ale nadal przekazują true/false stan z wejścia. Inne (NOT, AND, OR) samodzielnie obliczają wartość logiczną.

2. Ściągawka z węzłów logicznych

Te bloki odpowiadają na najczęstsze pytania o znaczenie true/false.

NOT

  • Wejścia: 1 wartość logiczna (true/false) pochodząca z poprzedniego węzła.
  • Wyjścia: odwrócona wartość logiczna i niezmienione dane zdarzenia.
  • Domyślne zachowanie: Jeśli do wejścia NOT nic nie jest podłączone, zwraca on false, więc wynikiem jest true.
Przykład: Umieść NOT za „Contains Keyword”, aby uruchomić alert, gdy widz nie używa słowa kluczowego.

AND

  • Wejścia: co najmniej dwa sygnały logiczne (A, B, ...). Dodatkowe porty możesz pozostawić puste.
  • Wyjścia: true tylko wtedy, gdy wszystkie podłączone wejścia mają wartość true.
  • Używaj AND, gdy kilka warunków musi być spełnionych jednocześnie ("jest subskrybentem" i "wiadomość czatu zawiera !raffle").

OR

  • Emituje true jeśli dowolne podłączone wejście ma wartość true.
  • Przydatne dla wyzwalaczy obejmujących wiele platform: połącz węzły wiadomości Twitch i YouTube z jednym OR, a następnie użyj wspólnej akcji.
Czy zawsze potrzebuję węzła AND?
Nie. Wiele węzłów zawiera już połączone filtry (np. "Filter User Level" + "Contains Text"). Używaj AND tylko wtedy, gdy wbudowane opcje nie obejmują potrzebnej kombinacji lub gdy chcesz utworzyć wspólny punkt logiczny używany przez inne gałęzie.
NOT i puste wejścia: Niepodłączony węzeł NOT nadal zwraca true. Podłącz go do sensownego źródła lub wyłącz węzeł, aby przypadkiem nie odblokował przepływu.

3. Przykładowe małe przepływy

A. Automatyczna odpowiedź, chyba że wiadomość jest komendą

Twitch Message ──▶ Regex Match "^!" ─┐ ├─false──▶ Automatyczna odpowiedź ("Dzięki za rozmowę!") └─true──▶ Nic nie rób

Tutaj węzeł Regex emituje true gdy wiadomość jest komendą. Kierujemy false wyjście do naszej odpowiedzi, więc zwykłe wiadomości czatu otrzymują potwierdzenie, a komendy po prostu przechodzą dalej.

B. Wymagaj spełnienia kilku warunków za pomocą AND

YouTube Message ──▶ Contains "!queue" ─▶ AND ─▶ Przekaż do Discorda Gifted Membership ─▶ User Role = Member ──▲

Węzeł AND sprawia, że do Discorda przekazywane są tylko wiadomości członków używających właściwego słowa kluczowego. Obie gałęzie wysyłają swój wynik logiczny do AND; dane zdarzenia z pierwszej gałęzi są przekazywane dalej.

C. Węzeł NOT blokujący powtarzające się alerty

Dane zdarzenia ─▶ State Check (isAlertMuted) └─false─▶ NOT ─▶ Play Celebration

State Check zwraca wartość true , gdy alert jest wyciszony. Odwracając ten wynik, węzeł NOT sprawia, że efekt świętowania odtwarzamy tylko wtedy, gdy flaga ma wartość false.

D. Losowe odtworzenie jednego z dwóch dźwięków

Przepływ z bramkami RANDOM, NOT i AND, który losowo odtwarza jeden z dwóch klipów audio
Losowanie jednego z dwóch klipów audio z prawdopodobieństwem 50/50. Bramka RANDOM losuje raz dla każdej pasującej wiadomości: gdy przepuszcza, odtwarzany jest dźwięk A; gdy odrzuca, bramka NOT odwraca wynik, a AND pozwala odtworzyć dźwięk B.
Wyzwalacz ──▶ RANDOM (50%) ──▶ Odtwórz dźwięk A │ └──▶ NOT ──▶ AND ──▶ Odtwórz dźwięk B Wyzwalacz ──────────────────▲

Bramka AND jest konieczna. Sam węzeł NOT zwróciłby true zawsze, gdy bramka RANDOM jest bezczynna, więc dźwięk B odtwarzałby się przy każdej wiadomości czatu, która nie pasuje do twojego wyzwalacza. Podanie wyzwalacza do AND jako drugiego wejścia ogranicza dźwięk B wyłącznie do pasujących wiadomości. Ten sam wzorzec działa dla dowolnej pary alternatywnych akcji, nie tylko dźwięków.

4. Zapobieganie echom, pętlom i ponownemu przekazywaniu wiadomości

Przekazywanie czatu między interfejsami daje duże możliwości, ale może tworzyć nieskończone echo, jeśli nasłuchujesz własnych wiadomości wyjściowych. Stosuj te zabezpieczenia:

Uwaga dotycząca miejsca docelowego YouTube Shorts:
Zarówno wyzwalacze przychodzące, jak i cele wychodzących akcji Relay Chat rozróżniają youtube i youtubeshorts. Użyj dwóch akcji przekazywania, jeśli wiadomość ma trafić do obu wariantów. Zobacz YouTube Shorts i Event Flow.
Relay Chat automatycznie pomija rozpoznane odbicia.
Odbicie to wysłana wiadomość ponownie przechwycona z docelowego czatu. Obecne akcje Relay Chat pomijają rozpoznane odbicia; nie ma osobnego pola No Reflections. Aby ukryć lub ograniczyć ich wyświetlanie w doku i nakładkach, użyj Filtr odbić (Reflection Filter) z parametrem Blokuj wszystkie (Block All), Zezwalaj na pierwsze (Allow First) lub Zezwalaj na wszystkie (Allow All). Określa to sposób wyświetlania po ponownym przechwyceniu, a nie wysyłanie. Postępuj zgodnie z przewodnikiem krok po kroku po przekazywaniu Twitch i YouTube aby uzyskać pełną konfigurację.
  • Unikaj powielania systemów przekazywania. Wyłącz globalne Relay all, jeśli używasz równoważnych tras Event Flow, i sprawdź, czy inne usługi nie łączą tych samych czatów. Nie ma gwarancji, że własne metadane przetrwają przesłanie przez czat platformy.
  • Używaj węzłów Debounce lub Cooldown dla alertów, które mają uruchamiać się najwyżej raz na X sekund.
  • Celowo przerywaj cykle. Jeśli dwie gałęzie przekazują dane do siebie nawzajem, dodaj węzeł logiczny sprawdzający zmienną stanu ("currentlyRelaying"), aby przepływ kończył się wcześniej, gdy flaga jest ustawiona.

5. Wejścia, wyjścia i pytania praktyczne

Co trafia do węzła?

  • Pełne dane wiadomości.
  • Bit warunku (true/false).
  • Opcjonalny kontekst (zmienne stanu, zegary), o który węzeł wyraźnie prosi.

Co wychodzi z węzła?

  • Te same dane zdarzenia, chyba że węzeł je zmieni.
  • Ponownie obliczony bit warunku (węzły logiczne) lub przekazany dalej bit (akcje).
  • Większość działań zewnętrznych (np. wysyłanie czatu) nie zmienia danych zdarzenia, ale akcje punktów mogą dodawać pola stanu, takie jak pointsTotal lub pointsSpendError do logiki w kolejnych krokach.

Kiedy tworzyć rozgałęzienia?

Gdy chcesz reagować inaczej na true a false. Przeciągnij przewód z wybranego kolorowego wyjścia (zielone = true, szare/czerwone = false) do następnego węzła.

Pamiętaj: Jeśli nic nie zrobisz z false wyjściem, przepływ po prostu się tam kończy. To dobre rozwiązanie dla filtrów ("blokuj wszystko, co nie przechodzi sprawdzenia"), ale pamiętaj o podłączeniu false ścieżki, jeśli potrzebujesz obsługi alternatywnej.

Częste pytania i odpowiedzi

  • Czy muszę używać AND przy każdej parze filtrów? Nie. Wiele węzłów obejmuje kilka sprawdzeń (np. podstawowy Message Filter obsługuje słowo kluczowe + rolę). Używaj AND tylko przy bardziej złożonych kombinacjach lub łączeniu sygnałów z różnych węzłów.
  • Jak wartości true/false docierają do węzła NOT? Każdy węzeł z zielonym wyjściem emituje true domyślnie. Gdy warunek nie jest spełniony, emituje false. Podłącz ten przewód do NOT, aby odwrócić wynik.
  • Czy węzeł może emitować dane, nawet jeśli zwraca false? Tak. Dane zdarzenia nadal przechodzą przez wyjście false; to ty decydujesz, dokąd ta gałąź ma prowadzić.
  • Jak rozpoznawać członków zespołu TikTok? Wybierz Członek zespołu TikTok w węźle User Role. Rozpoznaje poziomy i odznaki Fan Club/zespołu TikTok w przychodzącej wiadomości i nie zależy od ustawień Main Chat Overlay.
  • Czy każdy węzeł Speak Text może używać innego głosu? Tak. Wpisz nazwę lub identyfikator głosu obsługiwanego przez dostawcę w polu Nadpisanie głosu lub pozostaw pole puste, aby użyć domyślnego głosu TTS z Flow Actions.

6. Opis zmiennych szablonów

Kilka węzłów akcji (Show Text, Set Text Source, Send Message, Relay Chat, TTS Speak, Call Webhook, Print Thermal Label) obsługuje zmienne szablonów , które w czasie wykonania są zastępowane danymi zdarzenia. Nazwy zmiennych umieszczaj w nawiasach klamrowych, np. {username}.

Zmienne podstawowe (zgodne ze starszymi wersjami)

ZmiennaAliasOpisPrzykład
{username}{chatname}Nazwa wyświetlana użytkownikaCoolViewer123
{message}{chatmessage}Tekst wiadomości czatuCześć wszystkim!
{source}-Nazwa platformy (z wielkiej litery)Twitch, YouTube
{type}-Nazwa platformy (wartość surowa)twitch, youtube
{donation}{hasDonation}Etykieta wyświetlanej wpłaty/napiwku$5.00, 500 bits

Zmienne rozszerzone

ZmiennaOpisPrzykład
{displayname}Nazwa wyświetlana (alternatywne pole)CoolViewer123
{donoValue}Równowartość wpłaty w USD, podana lub oszacowana; Event Flow wyprowadza wartości progowe ze znormalizowanego hasDonation w postaci wartości, $wartość, wartość + jednostka lub skrócony zapis jednostki/wartości. Nieznane nazwane jednostki wirtualne są przeliczane jako 100 jednostek = $0.01 USD; prezenty TikTok bez ceny są liczone jako jedna moneta na prezent ($0.01 za sztukę). {donationAmount} to starszy alias5.00
{event}Identyfikator typu zdarzeniacheer, raid, new_follower
{membership}Stan członkostwaMEMBERSHIP, new_sponsor
{subtitle}Dodatkowy kontekstCzłonek od 3 miesięcy
{userid}Identyfikator użytkownika na platformie12345678
{chatimg}Adres URL awatara użytkownikahttps://...
{contentimg}Adres URL dołączonego obrazuhttps://...
{rewardTitle}Nazwa nagrody, gdy źródło udostępnia pole tytułu nagrody na najwyższym poziomieWyróżnij moją wiadomość
{meta}Ustrukturyzowane dane zdarzenia (JSON){"viewers":100}
{counterValue}Bieżąca wartość licznika po kroku Counter lub Check Counter12
{counterTarget}Wartość docelowa licznika30
{counterRemaining}Wartość docelowa licznika minus wartość bieżąca, z dolnym ograniczeniem do 018
Dopasowanie zmiennych nie rozróżnia wielkości liter. {USERNAME}, {Username} i {username} działają tak samo.
Pola dodane przez przepływ również działają. Jeśli wcześniejsza akcja dodaje do wiadomości wartość na najwyższym poziomie, późniejsze szablony mogą odczytać ją bezpośrednio. W ten sposób Check Counter udostępnia {counterValue}, {counterTarget} i {counterRemaining}.
JSON dla Call Webhook: Zmienne szablonów działają w tekstowych wartościach JSON na dowolnym poziomie zagnieżdżenia obiektów lub tablic. Klucze obiektów nie są przetwarzane jako szablony, a własna treść żądania bez symboli zastępczych jest wysyłana bez zmian.

Przykładowe szablony

  • Wyświetl tekst: {username} just cheered {hasDonation}!
  • Ustaw źródło tekstowe OBS: {username}: now {counterValue}, need {counterTarget}
  • Relay Chat: [{source}] {username}: {message}
  • TTS: {username} says {message}
  • Alert wpłaty: {username} donated {donation} - {subtitle}
  • Etykieta termiczna: {username}, nowy wiersz, a następnie {donation}. Zobacz Przewodnik po drukarce termicznej zawierający konfigurację drukarki, etykiety o stałym rozmiarze i kompletny przepływ.
  • Discord Call Webhook: {"content":"{message}","username":"{username}","avatar_url":"{chatimg}"}
Brakujące zmienne są zastępowane pustym tekstem. Jeśli zdarzenie nie zawiera danego pola (np. {donation} w zwykłej wiadomości czatu), symbol zastępczy jest zastępowany pustym tekstem zamiast wyświetlać dosłownie {donation} jako tekst.

7. Lista dobrych praktyk

  • Nadaj nazwy i kolory węzłom, aby w przyszłości było jasne, do czego służy każda gałąź.
  • Testuj przy użyciu wbudowanego symulatora (Send Test Event) przed uruchomieniem przepływu na żywo.
  • Grupuj logikę blisko źródła. Filtruj jak najwcześniej, aby ograniczyć przetwarzanie w kolejnych krokach.
  • Zapamiętuj powtórzenia w węzłach stanu. Używaj liczników, przełączników i znaczników czasu, aby unikać podwójnych alertów.
  • Dokumentuj pola meta. Gdy dodajesz własne klucze meta — opisz je, aby nakładki i zdalni klienci korzystali z nich spójnie.
Zapisuj wersje. Eksportuj przepływ po osiągnięciu ważnego etapu. Import to najprostszy sposób powrotu do poprzedniej wersji, jeśli eksperyment się nie powiedzie.

8. Dalsze możliwości

Uruchamiaj własne przepływy ze Stream Deck lub API: nazwane wyzwalacze, szablon początkowy, wykrywanie przepływów, dodatkowe dane, przykłady HTTP/WebSocket/P2P i gesty pokrętła.

Chcesz dowiedzieć się więcej?

  • Użyj Węzły stanu (liczniki, przełączniki, zegary), aby zachować kontekst między zdarzeniami.
  • Połącz Zmienne i logika do budowania kolejek, losowań lub systemów punktacji.
  • Podłącz się do systemu Punkty i nagrody , aby widzowie mogli celowo uruchamiać przepływy.
  • Korzystasz z aplikacji desktopowej SSApp? Odblokuj Węzły własnego JavaScript do dowolnej logiki, której nie obejmują wbudowane węzły.
  • Sprawdź Dokumentacja wydarzeń aby zapoznać się ze szczegółową dokumentacją danych zdarzeń wszystkich platform.

Ten przewodnik jest celowo samodzielny — skopiuj go lokalnie, dostosuj do swojego zespołu i eksperymentuj dalej w edytorze.

9. Własny JavaScript Tylko SSApp / aplikacja desktopowa

Dwa węzły edytora Event Flow pozwalają pisać dowolny JavaScript wykonywany w łańcuchu przetwarzania przepływu: Własny kod (Custom Code) (wyzwalacz) i Wykonaj własny kod (Execute Custom Code) (akcja). Pozwalają zrobić to, czego nie da się wyrazić za pomocą wbudowanych węzłów.

Wymagana aplikacja desktopowa. Węzły własnego JavaScript są wyłączone w rozszerzeniu przeglądarki, ponieważ zasady Content Security Policy w Chrome Manifest V3 blokują new Function() / eval(). Otwórz edytor przez Aplikacja desktopowa SSApp aby je włączyć. W trybie rozszerzenia węzły są wyszarzone i mają etykietę "Tylko aplikacja desktopowa".
Edycja kodu: wybierz węzeł Custom Code i kliknij Otwórz edytor kodu aby otworzyć duże okno edycji. Zapisz i zamknij sprawdza składnię JavaScript i zapisuje cały przepływ; Ctrl+S lub Cmd+S robi to samo. Cancel pozostawia węzeł bez zmian.
Edytor Event Flow — pusty stan
Edytor Event Flow. Lewy panel zawiera wszystkie dostępne węzły; na kropkowanym obszarze roboczym budujesz przepływy; prawy panel pokazuje właściwości wybranego węzła.

Custom Code — węzeł wyzwalacza

Przeciągnij Własny kod (Custom Code) z grupy Zaawansowane w panelu Wyzwalacze na obszar roboczy. Działa jako warunek: przepływ jest kontynuowany tylko wtedy, gdy kod zwraca true.

Panel wyzwalaczy z węzłem Custom Code w grupie Advanced
Custom Code znajduje się w grupie Zaawansowane w panelu Triggers.
Panel właściwości wyzwalacza Custom Code z edytorem JavaScript
Panel właściwości po dodaniu wyzwalacza. Wpisz dowolne wyrażenie zwracające true lub false.
Sygnatura: twój kod jest uruchamiany jako function(message) { ... }
Musi zwracać: wartość logiczną — true aby pozwolić przepływowi kontynuować, false aby go zatrzymać.
Dostępne: obiekt message (zobacz API message poniżej), a także convertCurrency(value, targetCurrency, source) i convertToUSD(value, source).

Execute Custom Code — węzeł akcji

Przeciągnij Wykonaj własny kod (Execute Custom Code) z grupy Integracje w panelu Akcje . Może zmieniać wiadomość, blokować ją lub dodawać metadane odczytywane przez kolejne węzły.

Panel akcji z Execute Custom Code w grupie Integrations
Execute Custom Code w grupie Integracje w panelu Actions.
Panel właściwości akcji Execute Custom Code z edytorem kodu
Właściwości akcji. Zwróć obiekt, aby scalić zmiany z wynikiem przepływu.
Sygnatura: twój kod jest uruchamiany jako function(message, result) { ... }
Powinien zwracać: obiekt lub Promise scalany z result— zobacz API result.
Dostępne: message (dane zdarzenia), result (bieżący stan wyniku przepływu), printThermal(html, options), a także convertCurrency(value, targetCurrency, source) i convertToUSD(value, source).
Druk termiczny w SSApp: wybierz drukarkę i skalibruj szerokość papieru oraz bezpieczne marginesy w Sterowanie drukarką (Printer Control), a następnie zwróć printThermal('<strong>' + message.chatname + '</strong>'). SSApp bez dodatkowych komunikatów kolejkuje zadanie przez natywny interfejs drukowania Windows, używając zapisanych ustawień. Przepływ może je nadpisać opcjami takimi jak { width: '58mm', marginLeft: '3mm', marginRight: '3mm', marginTop: '2mm', marginBottom: '2mm', feed: '3mm', marginType: 'printableArea' }. Zwrócenie Promise pozwala Event Flow zaczekać na przesłanie i zgłosić błędy.
Obszar roboczy z wyzwalaczem Custom Code i akcją Execute Custom Code obok siebie
Wyzwalacz Custom Code (niebieski) i akcja Execute Custom Code (zielona) umieszczone na obszarze roboczym. Połącz port wyjściowy wyzwalacza z portem wejściowym akcji.

Obiekt message

Oba węzły otrzymują pełne dane zdarzenia jako message. Poniższe pola są zawsze dostępne; zdarzenia konkretnych platform mogą zawierać dodatkowe pola.

PoleTyp danychOpisPrzykład
message.chatmessageciąg tekstowyTekst wiadomości czatu (może zawierać HTML)"Hello stream!"
message.chatnameciąg tekstowyNazwa wyświetlana nadawcy"CoolViewer"
message.useridciąg tekstowyIdentyfikator użytkownika na platformie"12345678"
message.typeciąg tekstowyPlatforma źródłowa (małymi literami)"twitch", "youtube", "kick"
message.hasDonationciąg tekstowySformatowany tekst wpłaty, jeśli jest dostępny"$5.00", "500 bits"
message.donoValueliczba / tekstRównowartość wpłaty w USD, jeśli źródło ją udostępnia; prawidłowe wartości zerowe są respektowane. Event Flow w razie potrzeby używa currency.js do przeliczania znormalizowanych etykiet hasDonation do porównań progowych, przyjmując między innymi 100 nieznanych nazwanych jednostek = $0.01 USD. Nie odczytuje kwot wpłat z tekstu pola chatmessage .5
message.eventciąg tekstowyIdentyfikator typu zdarzenia"new_follower", "cheer", "raid"
message.membershipciąg tekstowyStan członkostwa, jeśli dotyczy"MEMBERSHIP"
message.subtitleciąg tekstowyDrugi wiersz kontekstu"Member for 3 months"
message.modwartość logicznaNadawca jest moderatoremtrue
message.subscriberwartość logicznaNadawca jest subskrybentemtrue
message.vipwartość logicznaNadawca ma status VIPtrue
message.chatimgciąg tekstowyAdres URL awatara użytkownika"https://..."
message.metaobiektDowolne dane strukturalne dołączone do zdarzenia{ viewers: 120 }
Przeliczanie walut: użyj convertCurrency(message.hasDonation, 'EUR', message.type) aby przeliczyć sformatowaną etykietę wpłaty na EUR. Zwraca liczbę lub null , gdy żądana waluta docelowa nie jest obsługiwana. Przelicznik używa przybliżonych wewnętrznych kursów Social Stream Ninja; nie kontaktuje się z zewnętrzną usługą kursów walut.

Co zwraca akcja

Zwróć zwykły obiekt z kodu akcji. Wszystkie uwzględnione pola zostaną scalone z result ; pominięte pola zachowują bieżące wartości.

Zwracane poleTyp danychEfekt
modifiedwartość logicznaUstaw true jeśli zmienisz message . Informuje kolejne węzły, że dane zdarzenia zostały zmienione.
messageobiektZwróć wiadomość (ewentualnie zmienioną), aby kolejne węzły otrzymały twoje zmiany.
blockedwartość logicznaUstaw true aby uniemożliwić wyświetlenie lub przekazanie wiadomości.
Minimalna bezpieczna wartość zwracana: return { modified: false, message };
Nawet jeśli niczego nie zmienisz, zwrócenie message zapewnia przekazanie jej do następnego węzła.

Przykładowe fragmenty kodu

Wklej dowolny z tych przykładów do pola JavaScript Code w węźle odpowiedniego typu.

Fragmenty kodu wyzwalaczy — zwracaj true aby kontynuować przepływ

Dopasowanie słowa kluczowego (bez rozróżniania wielkości liter)
Kontynuuj przepływ tylko wtedy, gdy wiadomość zawiera określone słowo lub wyrażenie.
// Matches "!hello" anywhere in the message return (message.chatmessage || '').toLowerCase().includes('!hello');
Wykrywanie komend wyrażeniem regularnym
Dopasuj wiadomości zaczynające się od komendy z określonej listy (np. !queue, !raffle, !enter).
return /^!(queue|raffle|enter)\b/i.test(message.chatmessage || '');
Wpłata powyżej progu
Uruchom tylko wtedy, gdy wpłata osiąga lub przekracza minimalną kwotę.
const amount = message.donoValue !== undefined && message.donoValue !== null && message.donoValue !== '' ? Number(message.donoValue) : (typeof convertToUSD === 'function' ? convertToUSD(message.hasDonation || '', message.type || '') : Number(String(message.hasDonation || '').replace(/[^0-9.]/g, '') || 0)); return amount >= 5;
YouTube Super Chat lub Super Sticker w przedziale EUR
Przelicz standardową etykietę wpłaty YouTube na EUR, wyklucz Jewels/Gifts i wybierz jeden zakres dźwięku lub efektu wizualnego.
var eventName = String(message.event || '').toLowerCase(); if (eventName !== 'superchat' && eventName !== 'supersticker') return false; var eurValue = convertCurrency(message.hasDonation || '', 'EUR', message.type || ''); if (typeof eurValue !== 'number' || !isFinite(eurValue)) return false; message.eurValue = eurValue; return eurValue >= 10 && eurValue < 25;
Filtr platformy
Przetwarzaj tylko zdarzenia z określonych platform.
return ['twitch', 'youtube'].includes(message.type);
Warunek subskrybenta / VIP-a / moderatora
Pozwól kontynuować przepływ tylko użytkownikom z odpowiednimi uprawnieniami.
return !!(message.subscriber || message.vip || message.mod);
Wiele warunków — VIP + słowo kluczowe
Połącz sprawdzenie roli i treści wiadomości w jednym wyrażeniu, którego nie obsługuje żaden wbudowany wyzwalacz.
const isPrivileged = !!(message.subscriber || message.vip || message.mod); const isCommand = /^!feature\b/i.test(message.chatmessage || ''); return isPrivileged && isCommand;
Warunek długości wiadomości
Przetwarzaj tylko wiadomości zawierające wystarczająco dużo treści (przydatne w TTS lub przekazywaniu, aby unikać spamu pojedynczymi emoji).
return (message.chatmessage || '').replace(/<[^>]+>/g, '').trim().length >= 20;

Fragmenty kodu akcji — zwracaj { modified, message }

Dodaj odznakę lub znacznik do wiadomości
Dodaj wskaźnik wizualny na końcu każdej wiadomości przechodzącej przez tę akcję.
message.chatmessage = (message.chatmessage || '').trimEnd() + ' ✅'; return { modified: true, message };
Warunkowo zablokuj wiadomość
Sprawdź treść i bez komunikatu odrzuć wiadomość, jeśli pasuje do reguły — przydatne do wzorców spamu, których nie da się wyrazić filtrem słów kluczowych.
const text = (message.chatmessage || '').toLowerCase(); const spamPatterns = ['buy followers', 'free nitro', 'click here']; if (spamPatterns.some(p => text.includes(p))) { return { blocked: true, message }; } return { modified: false, message };
Usuń @wzmianki
Usuń wszystkie wzmianki @username z wiadomości przed przekazaniem jej na inną platformę.
message.chatmessage = (message.chatmessage || '').replace(/@\w+/g, '').trim(); return { modified: true, message };
Sformatuj komunikat o wpłacie
Zmień chatmessage na jednolicie sformatowany komunikat, jeśli występuje wpłata.
const amount = parseFloat(message.donoValue || 0); if (amount > 0) { const note = (message.chatmessage || '').trim(); message.chatmessage = `💰 ${message.chatname} donated $${amount.toFixed(2)}!` + (note ? ` "${note}"` : ''); return { modified: true, message }; } return { modified: false, message };
Dodaj metadane routingu dla kolejnych węzłów
Dodaj do wiadomości własne pole, które późniejszy Przekaż czat (Relay Chat) lub Wyślij wiadomość może odczytać ze zmiennej szablonu ({meta}).
message.meta = message.meta || {}; // Assign a donation tier so the next node can use {meta} to decide overlay colour const amount = parseFloat(message.donoValue || 0); message.meta.donationTier = amount >= 20 ? 'gold' : amount >= 5 ? 'silver' : 'bronze'; return { modified: true, message };
Prefiks wiadomości zależny od platformy
Przy przekazywaniu między platformami dodaj na początku etykietę platformy, aby widzowie znali źródło.
const labels = { twitch: '[Twitch]', youtube: '[YouTube]', kick: '[Kick]', tiktok: '[TikTok]', }; const label = labels[message.type] || `[${message.type || 'Chat'}]`; message.chatmessage = `${label} ${message.chatname}: ${message.chatmessage || ''}`; return { modified: true, message };

Pełny przykład — bot próśb o funkcje dla VIP-ów

Ten przepływ nasłuchuje !feature <text> od subskrybentów, VIP-ów lub moderatorów, formatuje ją jako prośbę o funkcję i przekazuje do drugiego miejsca docelowego (np. Discorda).

┌────────────────────────┐ ┌───────────────────────────┐ ┌──────────────────┐ │ Wyzwalacz Custom Code │─▶│ Akcja Execute Custom Code │─▶│ Relay Chat │ │ Warunek: VIP/sub/mod │ │ Zmień tekst wiadomości │ │ (do Discorda) │ │ + zaczyna się od │ │ → "📋 Prośba o funkcję │ │ │ │ !feature │ │ od {name}: {text}" │ │ │ └────────────────────────┘ └───────────────────────────┘ └──────────────────┘

Krok 1 — wyzwalacz Custom Code (wklej w polu JavaScript Code wyzwalacza):

// Only let VIPs, subscribers, and mods through, and only for !feature commands const isPrivileged = !!(message.subscriber || message.vip || message.mod); const isCommand = /^!feature\b/i.test((message.chatmessage || '').trim()); return isPrivileged && isCommand;

Krok 2 — akcja Execute Custom Code (wklej w polu JavaScript Code akcji):

// Strip the "!feature" command word and format a clean announcement const featureText = (message.chatmessage || '') .replace(/^!feature\s*/i, '') .trim(); if (!featureText) { // No text after the command: block rather than relay an empty request return { blocked: true, message }; } message.chatmessage = `📋 Feature request from ${message.chatname}: ${featureText}`; return { modified: true, message };

Krok 3 — akcja Relay Chat: dodaj za akcją standardowy węzeł Relay Chat i skonfiguruj docelowy Discord (lub inne miejsce). Własny kod nie jest tu potrzebny — przeformatowane message.chatmessage jest automatycznie przekazywane dalej.

Testowanie przepływu. Kliknij przycisk: Testuj przepływ (Test Flow) (w prawym górnym rogu edytora), aby wysłać syntetyczną wiadomość przez cały łańcuch bez transmisji na żywo. Ustaw chatname na subskrybenta, dodaj wiadomość taką jak !feature dark mode support i sprawdź, czy miejsce docelowe Relay Chat otrzymuje przeformatowany tekst.
Panel Test Flow do wysyłania syntetycznych zdarzeń testowych
Panel Test Flow. Wypełnij pola tak, aby odpowiadały warunkom wyzwalacza, i kliknij Uruchom test aby sprawdzić cały łańcuch przetwarzania.

Kwestie bezpieczeństwa

Własny kod działa z uprawnieniami procesu renderującego. W SSApp kod w węzłach Custom JS ma pełny dostęp do window oraz wszystkich API udostępnianych przez skrypt preload (np. window.ninjafy). Traktuj importowane pliki przepływów jak kod wykonywalny — importuj je wyłącznie z zaufanych źródeł.
  • Brak izolacji dostępu do sieci. Kod akcji może wywoływać fetch(). Jeśli przyjmujesz przepływy od innych osób, sprawdź kod JS przed ich aktywowaniem.
  • Błędy są przechwytywane. Błąd wykonania w twoim kodzie zwraca false (wyzwalacz) lub pominięcie działania (akcja) oraz zapis do konsoli DevTools — przepływ nie ulega awarii.
  • Dotyczy to także błędów składni. Błąd typu SyntaxError podczas kompilacji jest przechwytywany w ten sam sposób. Sprawdź DevTools (F12), jeśli węzeł pozornie nic nie robi.