Комплексна тема, але не менш цікава. Можу вас запевнити, якщо у вас ніколи не було досвіду з написанням коду, це не так складно, як здається. Я спробую максимально просто і доступно пояснити про програмування на мові C#, адже саме на цій мові написана програма. Зробимо кілька скриптів для чату на Twitch.
Вступ
Потрібно розуміти, що для користуванням Streamer.Bot займатись програмуванням геть не обов’язково. Ви можете й надалі використовувати sub-actions. Проте програмуванням можна замінити sub-actions, але sub-actions не можна замінити все програмування і я скажу по своєму досвіду, що використання sub-actions іноді є навіть складнішим. Це відкриває величезний спектр функціоналу, який можна зробити. Наведу приклади того, що робив я:
Гра в Морквину. Користувач пише !реєстрація, отримує морквину 50 см. Далі він може писати !морква і він отримує від -10 до 10 см раз на 24 години. Користувачі можуть виводити топ-5 найбільших і топ-5 найменших морквин в чаті.
Команда !шо @нікнеймстримера - кидає на стримера shoutout і виводить браузерне джерело на стрим з його кліпом, з можливістю відфільтрувати ці кліпи.
Через редімку, в якій треба писати текст, пишеться населений пункт. Використовується API погоди, щоб виводити на стрим погоду на кілька днів перед.
Команда !vs @Назвапершогообласногоцентру @Назвадругогообласногоцентру (Наприклад: !vs Львів Тернопіль), де випадковим чином один із обласних центрів перемагає і у кожного є свій рахунок перемог.
Зберігання усі повідомлень в чаті на комп’ютері для логу.
Це лише маленький приклад того, що я вже робив.
Найголовніше: якщо ви хоч раз подумали "було б круто зробити...", але не знайшли готового SA — швидше за все, це можна зробити через код.
Що таке C# і код?
Код — це інструкції для комп'ютера. Так само, як ви пишете список дій у Sub-Actions (зробити це, потім те), код — це той самий список, але більш гнучкий і потужний.
C# (Сі-шарп) — це мова програмування. Це як англійська, тільки для спілкування з комп'ютером. Є багато таких мов (Python, JavaScript, Java), але Streamer.bot використовує саме C#.
Чому саме C#? Програма зроблена за допомогою WPF - Windows Presentation Foundation (до версії SB 1.0 це був WinForms), це розробка компанії Microsoft. C# являється також продуктом Майків, тому цілком логічно, що технологія, як і більшість технологій Microsoft працюють на цій мові. WPF дозволяє розробляти всілякі програмки з графічним інтерфейсом (кнопками, вікнами, картинками, тощо).

Крок 1. Створення першого SA → Execute C# Code
Давайте зробимо нову дію (action), назвемо її “Тест”, зробимо Test-тригер і додаймо Sub-actions → Core → C# Code → Execute C# Code
Після додавання, ви побачите таке вікно. Давайте його розберем.

using System;- це використання бібліотеки функцій C#. Таких бібліотек багато. Вони потрібні для різних галузей: ігри, AI, мережа, Бази Даних, робота з файлами, тощо.public class CPHInline { }Це блок для нашого коду.
class- це контейнер, де виконується наш код. Всередині нього знаходиться:Змінні - це дані, які ми зберігаємо, їх ще називають атрибутами.
Методи (функції) - це дії, які ми можемо виконатию
Метод - це функція, яка належить класу. Коли ви бачите:
CPH.SendMessage("Привіт!");Це означає:
CPH- це клас (контейнер з інструментами від Streamer.bot)SendMessage- це метод (функція) всередині класу CPHКрапка
.означає "візьми з CPH метод SendMessage"
Просто запам’ятайте те, що всередині цього CPHInline ми маємо писати код. Дужки
{ }відповідають за відкриття та за закриття блоку з кодом.Дуже крутий приклад класу є class Car. Car може мати вагу, колір, кількість колес, сидінь, дверей, тощо - це все атрибути. Також, машина може мати якісь методи (функції) - їхати, гальмувати, прискоритись, здати назад і тощо.
public bool Execute() { // your main code goes here* return true; }Execute()- це функція, яка запускається при виконані Execute C# Code (тобто коли ми тригеремо подію). Код, як і в SA, спрацьовує зверху вниз.return true;- каже SB "все добре, продовжуй виконувати інші SA".return false;— виконання цілої дії (Action) зупиниться.// your main code goes here- Це коментар. Все, що написано після//— ігнорується комп'ютером. Це для вас, щоб робити нотатки.
Ви можете подивитись на таблицю, щоб дізнатись, що роблять клавіши в вікні:
Action | Description |
|---|---|
Format Document | Автоматично форматує код із правильним відступом |
Find Refs | Спробуйте автоматично знайти деякі загальні посилання на основі ваших директив |
Compile | Перевіряє компіляцію вашого коду та перевіряє наявність помилок. |
Save and Compile | Зберігає ваші зміни та попередньо скомпільовує код, щоб він був готовий до роботи з першого разу, коли буде виконана дія. |
Ok | Зберегти ваші зміни |
Cancel | Скасувати ваші зміни |
Примітка. Метод - це функція, яка належить класу. У C# фіча заключається в тому, що все побудоване на класах. Тому, якщо я пишу слово функція, або метод, то це одне й те саме.
Крок 2. Перша програма
Давайте спробуємо написати Send Message in Chat, як ми робили в першій статі. Виведемо наступне: “Привіт, світ!”, але через код.
У Streamer.Bot є клас CPH. Цей клас містить методи, які ми можемо викликати. Щоб переглянути список цих методів, ви можете перейти за цим посиланням: https://docs.streamer.bot/api/csharp/methods Якщо вам буде цікаво, то я напишу окрему статтю, де розберу усі методи.
Нам потрібен метод SendMessage. Щоб його викликати, нам потрібно звернутись до класу, до якого належить метод CPH, через крапку написати цей метод і в дужках передати параметри, якщо вони є. У документації цього метода, ви побачите наступне:
public void SendMessage(string message, bool useBot = true, bool fallback = true)Те, що в дужках, це параметри функції. Сюди ми передаємо ті значення, які нам потрібні. Не всі параметри є обов’язковими, лише
message. Сюди ми передаймо наш текст.Код програми виглядатиме наступним чином:
using System;
public class CPHInline
{
public bool Execute()
{
CPH.SendMessage("Привіт, світ");
return true;
}
}Тепер ми можемо перевірити, чи написали код правильно. Вам достатньо натиснути клавішу Compile. Якщо все буде гаразд, ви отримаєте повідомлення: “Compiled successfully!”. Якщо буде помилка, то ви отримаєте повідомлення про помилку. Зліва буде написано на якому рядку вона знаходить і її причина.
Дуже важливо правильно писати усі слова, регістр (велика/маленька літера), не забувати закривати дужки, ставити вкінці інструкцій ;
Натискаємо Save and Compile/Ok. Вікно закриється і тепер ми можемо протестувати наш код. Переходимо то тригера, натискаємо ПКМ і клацаємо Test Trigger.

Вітаю, ви написали першу програму!
Базові концепції в програмуванні
Перед тим, як рухатись далі, розберемо основні поняття у програмуванні. Я пояснюватиму максимально просто.
Змінні (Variables)
Змінна - це контейнер, для зберігання значень даних. Вони бувають різними, числовими, текстовими і так далі. Пам’ятаєте цей рядок коду з методом, який виводить повідомлення в чат?
public void SendMessage(string message, bool useBot = true, bool fallback = true)Я не розповів вам про слова, які знаходяться біля параметрів: string, bool і тощо. Це є типи змінних, якщо вони вказані в функції, то такі змінні треба передавати в функції. Змінні бувають:
int- зберігає цілі (цілі числа) без десяткових знаків, наприклад 123 або -123double- зберігає числа з плаваючою комою з десятковими дробами, наприклад 19,99 або -19.99char- зберігає окремі символи, такі як 'a' або 'B'. Значення символів оточені одинарними лапкамиstring- зберігає текст, наприклад "Hello World!" Рядкові значення взяті в подвійні лапкиbool- зберігає значення з двома станами: true або false
Щоб створити змінну, потрібно вказати тип і призначити їй значення:
type variableName = value;Де type – це тип C# (наприклад int або string), а variableName — це ім’я змінної (наприклад, x або name). Знак рівності використовується для призначення значень змінній.
Приклад змінних:
string viewer = "Олексій";
int age = 25;
CPH.LogInfo("Глядач " + viewer + " має " + age + " років");
// Виведе: Глядач Олексій має 25 роківДУЖЕ ВАЖЛИВО
Якщо верхній код спрацює, то цей ні:
int points = 100;
CPH.LogInfo(points); // ❌ ПОМИЛКАВи отримаєте помилку: cannot convert from 'int' to 'string’. Це стається через те, що метод LogInfo приймає першим параметром значення типу string, але ми передаємо число - int. Як це виправити? Є кілька варіантів:
Конкатенація з текстом:
int points = 100; CPH.LogInfo("Кількість балів: " + points); // ✅ ПрацюєКоли ви додаєте число до тексту через
+, C# автоматично перетворює число в текст.Метод .ToString() Цей метод здатен перетворювати будь-який тип даних в текст.
int points = 100; CPH.LogInfo(points.ToString()); // ✅ ПрацюєІнтерполяція рядків
int points = 100; CPH.LogInfo($"Кількість балів: {points}"); // ✅ Працює
Примітка. Коли ми будемо користуватись змінними в Streamer.Bot звертайте увагу на те, який тип змінних ви хочете вивести в чат, або в логи. Вони завжди мають бути типом string.
Оператори
Оператори використовуються для виконання операцій над змінними та значеннями.
У прикладі нижче ми використовуємо оператор +, щоб додати два значення:
int x = 100 + 50;Оператор | Назва | Опис | Приклад |
|---|---|---|---|
+ | Додавання | Додає два значення | x +y |
- | Віднімання | Віднімає одне значення від іншого | x - y |
* | Множення | Множить два значення | x * y |
/ | Ділення | Ділить одне значення на інше | x / y |
% | Модуль | Повертає залишок від ділення | x % y |
++ | Інкремент | Збільшує значення змінної на 1 | x++ |
— | Декремент | Зменшує значення змінної на 1 | x-- |
Також існують логічні оператори. Вони будуть використовуватись в 99% у конструкціях if/else:
Оператор | Назва | Опис | Приклад |
|---|---|---|---|
&& | Логічне and | Повертає True, якщо обидва твердження істинні | x < 5 && x < 10 |
Логічне or | |||
! | Логічне not | Перевертає результат, повертає False, якщо результат істинний | !(x < 5 && x < 10) |
Умови (if/else)
Я вже вам розповідав основне про конструкцію if/else в статі про sub-actions, але ми повторимо цю базу.
Конструкція розшифровується “якщо/інакше”. Уявіть собі ситуацію із реального життя: Ви хочете вийти з дому, але перед цим дивитесь прогноз погоди і думаєте: “Якщо буде дощ → я візьму парасольку, Інакше я не буду брати парасольку”.
If/else - це конструкція, яка відповідає за те, яку ми умову ставимо собі/програмі/комусь і що відбудеться. Як це виглядає в коді?
Структура:
if (умова)
{
// виконується, якщо умова ІСТИННА (true)
}
else
{
// виконується, якщо умова ХИБНА (false)
}
C# підтримує звичайні логічні умови з математики:
Менше ніж: a < b
Менше ніж або дорівнює: a <= b
Більше ніж: a > b
Більше ніж або дорівнює: a >= b
Дорівнює a == b
Не дорівнює: a != bПриклад:
int points = 50;
if (points >= 50)
{
CPH.LogInfo("У вас більше, або рівно 50 балів!"); //програма зайде в цей блок
}
else
{
CPH.LogInfo("У вас менше 50-ти балів"); // цей блок програма пропустить
}Також ми можемо використовувати кілька умов, додаючи після else if:
int points = 50;
if (points > 50)
{
CPH.LogInfo("У вас більше 50-ти балів!"); //Умова хибна, сюди не зайде
}
else if (points == 50)
{
CPH.LogInfo("У вас 50 балів"); //Умова істинна, сюди зайде і виведе повідомлення
}
else
{
CPH.LogInfo("У вас менше 50-ти балів"); //Умова хибна
}Цикли (while, for, foreach)
Цикл — це повторення якоїсь дії кілька разів. Наприклад: я хочу купити 10 яблук, я не покладу їх водночас усі в кошик, я буду брати їх по одному. Цикли допомагають не писати один той самий код n-кількість разів. Замість цього, достатньо написати блок, написати умову скільки разів треба, щоб один той самий блок виконався і все.
Цикл for використовується коли заздалегідь знаєш, скільки разів виконається цикл.
Виглядає конструкція наступним чином:
for (інструкція 1; інструкція 2; інструкція 3)
{
// блок коду для виконання
}Інструкція 1 виконується (один раз) перед виконанням блоку коду.
Інтсрукція 2 визначає умову для виконання блоку коду.
Інструкція 3 виконується (щоразу) після виконання блоку коду.
У прикладі нижче будуть надруковані числа від 0 до 10:
for (int i = 0; i < 10; i++)
{
CPH.LogInfo(i);
}Інструкція 1 встановлює змінну перед початком циклу (int i = 0).
Інструкція 2 визначає умову виконання циклу (i має бути меншим за 10). Якщо умова true, цикл розпочнеться знову, якщо умова false, цикл завершиться.
Інструкція 3 збільшує значення (i++) кожного разу, коли виконується блок коду в циклі.
Ще один приклад, де друкуватимуться лише парні значення чисел від 0 до 10:
for (int i = 0; i <= 10; i = i + 2)
{
CPH.LogInfo(i);
}Цикл while перебирає блок коду, доки виконується задана умова, тобто є True:
while (умова)
{
// блок коду для виконання
}У наведеному нижче прикладі код у циклі виконуватиметься знову і знову, доки значення змінної (apples) менш як 10:
int apples = 0;
while (apples < 10)
{
CPH.LogInfo(apples);
apples++;
}Примітка. Будьте обачні, яку умову ви пишете в while. Може трапитись нескінчений цикл.
Також існує цикл do while Різниця заключається лише в тому, що do while виконає дію точно один раз і вже потім буде перевіряти умову while
int apples = 13;
do {
apples--;
CPH.LogInfo(apples);
} while (apples > 10);Можу сказати з впевненістю 90%, що вам while не знадобиться. Він не дуже добре читається. Проте заради цих 10% він тут розписаний. Рекомендую використовувати цикл for.
Цикл foreach використовується для перебору елементів у колекції (наприклад, масиві або списку).
Структура:
foreach (type variableName in arrayName)
{
// блок коду для виконання
}Приклад:
List<string> names = new List<string>{"Олег", "Марія", "Андрій"};
foreach (string name in names)
{
CPH.LogInfo(name);
}
// Виведе: Олег, Марія, АндрійПримітка. Якщо ви не зрозуміли коду зверху, або що таке масиви, чи списки - це абсолютно нормально. У наступному пункті, ми про них поговоримо
Масиви (arrays)
Масиви - використовуються для зберігання кількох значень в одній змінній замість оголошення окремих змінних для кожного значення.
Щоб оголосити масив, визначте тип змінної за допомогою квадратних дужок:
string[] namesУ масив ми можемо, наприклад покласти імена людей і призначати комірку, в якій вони будуть знаходитись а потім звертатись до цієї комірки:
string[] names = new string[5]; // Масив на 5 елементів
names[0] = "Олег";
names[1] = "Марія";
names[2] = "Андрій";Зверніть увагу на те, що індексація масивів починається з 0, тобто перший елемент буде мати комірку [0], а не [1].
Якщо ми визначаємо, що масив на 5 елементів, то ми не зможемо додати 6-ий елемент. Це зручно, якщо ми знаємо фіксовану кількість змінних, яку ми хочемо додати до масиву. Такий масив виглядатиме так:
Індекс | Значення |
|---|---|
0 | "Олег" |
1 | "Марія" |
2 | "Андрій" |
3 |
|
4 |
|
Ми можемо створювати їх ще так. У такому випадку масив створюється з елементами, програма визначає, що розмір такого масиву - 3:
string[] names = {"Олег", "Марія", "Андрій"};
int[] myNum = {10, 20, 30, 40};Приклад використання масиву з циклом for:
string[] viewers = {"Олег", "Марія", "Андрій"};
CPH.LogInfo("Перший глядач: " + viewers[0]); // Олег
CPH.LogInfo("Кількість: " + viewers.Length); // 3 (Length зберігає довжину масиву)
// Перебір масиву
for (int i = 0; i < viewers.Length; i++)
{
CPH.LogInfo(viewers[i]);
}Якщо ми хочемо змінити цей масив, додати змінну, чи навпаки звідти її прибрати, доведеться створювати вже новий масив. Якщо вам потрібно саме змінювати ваш масив, у такому разі, C# здатен створювати їх динамічно - це називається Списками.
Списки (List)
Списки - це динамічна колекція елементів одного типу. Розмір списку може змінюватись - можна додавати і видаляти елементи, не створюючи новий список. Це такий собі масив на максималках.
Перевага списків є в тому, що вони можуть змінюватись динамічно. Вони мають методи, які дозволяють їх збільшувати, зменшувати, очищати, вставляти всередину списку елемент. Створення списку:
List<string> viewers = new List<string>();
viewers.Add("Олег");
viewers.Add("Марія");
viewers.Add("Андрій");
// Можна додавати скільки завгодно!
// Або одразу з значеннями
List<int> numbers = new List<int> {10, 20, 30, 40, 50};У вас може виникнути питання, чому взагалі потрібні тоді масиви, якщо є списки? Потрібно розуміти, що тоді коли їх придумали, комп’ютери були значно слабші за ті, які у нас зараз. Кожен байт пам’яті був важливий. Проте з часом, коли комп’ютери ставали краще, було зроблено списки, які є зручнішими у використанні, жертвуючи продуктивністю. Уявіть собі 10 000 000 записів одного типу. Масив може опрацювати їх за, умовно, 30 секунд, коли список це зробить за 60 секунд. А що якщо це не 10 000 000, а скажімо 1 000 000 000?
Примітка. Для нашої роботи це не має значення, адже, що списки, що масиви, в нашому випадку будуть виконувати свою роботу за мілісекунди, тому пункт про масиви можна було пропустити, але це фундаментальний розділ в програмуванні. Для написання скриптів, ми будемо користуватись Списками.
Таблиця корисних методів для списків:
Метод / властивість | Що робить | Приклад |
|---|---|---|
| Додає елемент в кінець |
|
| Додає колекцію |
|
| Видаляє перше входження |
|
| Видаляє за індексом |
|
| Видаляє за умовою |
|
| Очищає список |
|
| Перевіряє наявність |
|
| Індекс елемента |
|
| Кількість елементів |
|
| Виділена памʼять |
|
| Сортує список |
|
| Розвертає |
|
| Перший елемент за умовою |
|
| Всі елементи за умовою |
|
| Чи є хоча б один |
|
| Дія для кожного |
|
| Перетворює в масив |
|
Це основне в програмуванні, що треба знати вам для того, щоб писати скрипти або навіть програми. Я дуже рекомендую використати цей сайт: https://dotnetfiddle.net/ тут ви можете попрактикуватись здобутими знаннями. Також, у корисних посиланнях я залишу онлайн-посібник по C#. Там написано дуже доступно і структуровано.
Давайте тепер перейдемо до того, як користуватись середовищем Streamer.Bot.
Робота зі змінними в коді
Ви пам'ятаєте змінні з Streamer.bot? %user%, %message%, %tier%? У коді ми можемо з ними працювати.
Отримання змінних з SB
Якщо ви раніше користувались Streamer.Bot і використовували код, можливо ви бачили такий синтаксис:
string user = args["user"];Це старий синтаксис отримання змінної %user% . У документації зазначено наступне:
Найкраще отримувати аргументи за допомогою CPH.TryGetArg(), доданого в Streamer.bot v0.2.3.
Не використовуйте прямий доступ до властивості argsу своєму коді! Прямий доступ до цієї властивості є небезпечним і може призвести до збою в роботі коду.
Отримати зміну ми можемо наступним чином в коді:
CPH.TryGetArg("user", out string user);Давайте розберемо детально цей рядок:
CPH.TryGetArg— метод для безпечного отримання змінної"user"— назва змінної (без %)out string user— створити зміннуuserтипуstringі покласти туди значення
Приклад:
public bool Execute()
{
// Отримати нікнейм користувача
CPH.TryGetArg("user", out string user);
// Вивести привітання
CPH.LogInfo("Привіт, " + user + "!");
return true;
}Що якщо змінна, яку ми використовується ще не існує? Наш код зламається і поверне false. Тому можемо перевіряти змінну:
public bool Execute()
{
// Спробувати отримати змінну
if (!CPH.TryGetArg("rawInput", out string input))
{
CPH.LogInfo("Помилка: немає тексту!");
return false; // Зупинити виконання
}
// Якщо змінна є, працюємо з нею
CPH.LogInfo("Ви написали: " + input);
return true;
}Це може бути корисно, якщо ми хочемо, наприклад, зробити команду !following @нікнеймлюдини але людини з таким нікнеймом на Twitch не існує.
Глобальні змінні
Ось тут я вже говорив вам про глобальні змінні. Якщо дуже коротко - це змінні, які не прив’язані до конкретного користувача, а слугують тим, щоб зберігати якесь спільне значення. Наприклад:
Список учасників в міні-грі
Лічильник нецензурних слів стримера
Ціль по підписниках
Лічильник фоловерів (так, існує такий аргумент, але ви з нього можете зробити глобальну змінну)
Так ось, існують методи, які дають можливість користуватись цими змінними не через sub-actions, а не через код. Давайте зробимо приклад і розглянемо його покроково.
Спробуємо отримати глобальну змінну testPoints
public bool Execute()
{
// Отримати кількість балів
int points = CPH.GetGlobalVar<int?>("testPoints", true) ?? 0;
// ?? 0 означає: якщо змінної немає, використати 0
return true;
}
Ми намагаємося зі змінної testPoints отримати значення і передати його в змінну points. Оскільки в нас немає ще глобальної змінної testPoints (вона дорівнює null, null - це нічого немає), тому int points = 0
Тепер давайте спробуємо надати значення і зберегти нашу глобальну змінну:
public bool Execute()
{
int points = CPH.GetGlobalVar<int?>("userPoints", true) ?? 0;
int newPoints = 150;
CPH.SetGlobalVar("testPoints", newPoints, true);
return true;
}
При спрацьовуванні тригера, у нас створиться змінна testPoints, яка матиме значення 150:

Користувацькі глобальні змінні
Важливе нагадування. Коли я розповідав про Користувацькі глобальні змінні тут, було зазначено, щоб знайти користувача і його змінні, нам треба обрати його платформу спочатку, і я вказував Twitch. Це дуже важливо, оскільки для кожної платформи існують свої методи:
GetKickUserVar
SetKickUserVar
GetTrovoUserVar
SetTrovoUserVar
GetTwitchUserVar
SetTwitchUserVar
GetYouTubeUserVar
SetYouTubeUserVar
Ми будемо користуватись методами, що пов’язані з Twitch.
Отримати змінну користувача. Оскільки я користуюсь Test Trigger, він не зберігає аргумент про те, хто його активував, тому я в метод GetTwitchUserVar буду передавати свій нікнейм:
CPH.TryGetArg("userName", out string userName);
int points = CPH.GetTwitchUserVar<int?>(userName, "points", true) ?? 0;Зберегти змінну користувача:
CPH.TryGetArg("userName", out string userName);
CPH.SetTwitchUserVar(userName, "points", 100, true);Працює аналогічно для звичайних глобальних змін, але для користувача:

Фухх. Я розповів вам основу та базу того, як писати код в Streamer.Bot. Тепер ви можете самі спробувати проекспериментувати. Якщо у вас щось не виходить, то в Корисних посиланнях завжди є посилання, де ви можете задати питання.
Прості приклади для стриму
Давайте тепер перейдемо до більш практичних прикладів (Усі приклади ви можете використовувати у себе).
Команда !dice
Створимо команду, яка кидає кубик від 1 до 6.
using System;
public class CPHInline
{
public bool Execute()
{
// Отримати нікнейм користувача
CPH.TryGetArg("user", out string user);
// Створити випадкове число від 1 до 6
Random random = new Random();
int diceResult = random.Next(1, 7); // 7 не включається!
// Вивести результат у чат
CPH.SendMessage(user + " кинув кубик і випало: " + diceResult, true);
return true;
}
}Результат:

Команда !filp
Команда, яка підкидає монетку і виводить результат в чат:
using System;
public class CPHInline
{
public bool Execute()
{
CPH.TryGetArg("user", out string user);
// Випадкове число 0 або 1
Random random = new Random();
int flip = random.Next(0, 2);
// Визначити результат
string result = (flip == 0) ? "Орел" : "Решка";
CPH.SendMessage(user + " підкинув(-ла) монетку: " + result + "!", true);
return true;
}
}Пояснення: (flip == 0) ? "Орел" : "Решка" — це короткий запис if/else.
Якщо flip дорівнює 0 → "Орел”
Інакше → "Решка”
Результат:

Лічильник смертей
Зберігає і виводить кількість смертей на стримі.
using System;
public class CPHInline
{
public bool Execute()
{
// Отримати поточну кількість смертей
int deaths = CPH.GetGlobalVar<int?>("deathCounter", true) ?? 0;
// Збільшити на 1
deaths++;
// Зберегти нове значення
CPH.SetGlobalVar("deathCounter", deaths, true);
// Вивести в чат
CPH.SendMessage("Кількість смертей: " + deaths, true);
return true;
}
}
Результат:

Вгадати число
!вгадати- почати гру!вгадати 50- спроба вгадати число 50
using System;
public class CPHInline
{
public bool Execute()
{
CPH.TryGetArg("user", out string user);
CPH.TryGetArg("userName", out string userName);
CPH.TryGetArg("rawInput", out string input);
// Перевірка чи є активна гра
int secretNumber = CPH.GetGlobalVar<int?>("guessGame_secret", false) ?? 0;
int attempts = CPH.GetGlobalVar<int?>("guessGame_attempts", false) ?? 0;
// Якщо гри немає - почати нову
if (secretNumber == 0)
{
Random random = new Random();
secretNumber = random.Next(1, 101);
CPH.SetGlobalVar("guessGame_secret", secretNumber, false);
CPH.SetGlobalVar("guessGame_attempts", 0, false);
CPH.SendMessage("🎲 Нова гра! Вгадайте число від 1 до 100! Пишіть !вгадати [число]", true);
return true;
}
// Перевірка чи введено число
if (string.IsNullOrEmpty(input))
{
CPH.SendMessage("Використання: !вгадати [число]", true);
return false;
}
// Спроба конвертувати в число
if (!int.TryParse(input, out int guess))
{
CPH.SendMessage("Будь ласка, введіть число!", true);
return false;
}
// Перевірка діапазону
if (guess < 1 || guess > 100)
{
CPH.SendMessage("Число має бути від 1 до 100!", true);
return false;
}
// Збільшити лічильник спроб
attempts++;
CPH.SetGlobalVar("guessGame_attempts", attempts, false);
// Перевірка відповіді
if (guess == secretNumber)
{
// Виграш!
int reward = Math.Max(1000 - (attempts * 50), 100); // Менше спроб = більший приз
int points = CPH.GetTwitchUserVar<int?>(userName, "points", true) ?? 0;
CPH.SetTwitchUserVar(userName, "points", points + reward, true);
CPH.SendMessage($"🎉 {user} вгадав число {secretNumber} за {attempts} спроб! Приз: {reward} балів!", true);
// Скинути гру
CPH.SetGlobalVar("guessGame_secret", 0, false);
CPH.SetGlobalVar("guessGame_attempts", 0, false);
}
else if (guess < secretNumber)
{
CPH.SendMessage($"📈 {user}, моє число БІЛЬШЕ ніж {guess}! (Спроба {attempts})", true);
}
else
{
CPH.SendMessage($"📉 {user}, моє число МЕНШЕ ніж {guess}! (Спроба {attempts})", true);
}
return true;
}
}
Результат:

Магічна куля
Відповідає на питання користувача випадковою відповіддю.
using System;
using System.Collections.Generic;
public class CPHInline
{
public bool Execute()
{
CPH.TryGetArg("user", out string user);
CPH.TryGetArg("rawInput", out string question);
// Перевірка чи задано питання
if (string.IsNullOrEmpty(question))
{
CPH.SendMessage($"{user}, задай питання! Використання: !куля [питання]", true);
return false;
}
// Список можливих відповідей
List<string> answers = new List<string>
{
// Позитивні відповіді (10)
"🔮 Так, абсолютно точно!",
"🔮 Безсумнівно так!",
"🔮 Без сумнівів!",
"🔮 Так, визначено!",
"🔮 Можеш покладатися на це!",
"🔮 Як я бачу, так!",
"🔮 Найімовірніше так!",
"🔮 Перспективи хороші!",
"🔮 Знаки вказують на так!",
"🔮 Так!",
// Нейтральні відповіді (5)
"🔮 Відповідь туманна, спробуй ще раз...",
"🔮 Запитай пізніше...",
"🔮 Краще не говорити тобі зараз...",
"🔮 Неможливо передбачити зараз...",
"🔮 Зосередься і запитай знову...",
// Негативні відповіді (5)
"🔮 Не розраховуй на це...",
"🔮 Моя відповідь - ні...",
"🔮 Мої джерела кажуть ні...",
"🔮 Перспективи не дуже хороші...",
"🔮 Дуже сумнівно..."
};
// Вибрати випадкову відповідь
Random random = new Random();
int index = random.Next(0, answers.Count);
string answer = answers[index];
// Відповісти
CPH.SendMessage($"{user} питає: \\"{question}\\" | {answer}", true);
return true;
}
}
Результат:

Зробити комплімент комусь в чаті
!комплімент @нікнейм- комплімент @нікнейму
using System;
using System.Collections.Generic;
public class CPHInline
{
public bool Execute()
{
CPH.TryGetArg("user", out string user);
CPH.TryGetArg("input0", out string targetInput);
// Перевірка чи вказано цільового користувача
if (string.IsNullOrEmpty(targetInput))
{
CPH.SendMessage($"{user}, вкажи кому хочеш зробити комплімент! Використання: !комплімент @нікнейм", true);
return false;
}
string target = targetInput.TrimStart('@');
// Перевірка чи не намагається комплементувати сам себе
if (target.ToLower() == user.ToLower())
{
CPH.SendMessage($"{user}, не можна комплементувати самого себе! Зроби комплімент комусь іншому! 😊", true);
return false;
}
// Категорії комплементів
List<string> personality = new List<string>
{
"має неймовірну харизму",
"справжня душа компанії",
"завжди позитивний/а",
"дуже добрий/а і чуйний/а",
"має золоте серце",
"вміє підтримати в важку хвилину",
"завжди чесний/а",
"дуже вірний/а друг"
};
List<string> skills = new List<string>
{
"дуже розумний/а",
"має неймовірний талант",
"справжній професіонал",
"дуже креативний/а",
"має золоті руки",
"вміє знайти вихід з будь-якої ситуації",
"має чудове почуття гумору",
"завжди знає правильні слова"
};
List<string> appearance = new List<string>
{
"має чудову усмішку",
"просто світиться від краси",
"має неймовірний стиль",
"виглядає чудово",
"має магнетичний погляд",
"дуже харизматичний/а"
};
// Випадково обрати категорію
Random random = new Random();
int category = random.Next(0, 3);
string compliment = "";
string categoryName = "";
if (category == 0)
{
compliment = personality[random.Next(0, personality.Count)];
categoryName = "Особистість";
}
else if (category == 1)
{
compliment = skills[random.Next(0, skills.Count)];
categoryName = "Навички";
}
else
{
compliment = appearance[random.Next(0, appearance.Count)];
categoryName = "Вигляд";
}
CPH.SendMessage($"💝 [{categoryName}] {user} → {target}: {compliment}! ✨", true);
return true;
}
}
Результат:

Висновок
Підведемо підсумки. Сьогодні ми розібрали з вами доволі комплексну, але, на мою думку, потрібну, цікаву й важливу тему для Streamer.Bot, а саме програмування. Я намагався якомога простіше пояснити те, як писати скрипти для того, щоб додати інтерактивність. Ми з вами розібрали найбазовішу інформацію про конструкції, які дозволяють вже писати цікаві програмки. Не забувайте про те, що ви завжди можете зв’язатись зі мною, або приєднатись до мого Discord серверу з обговоренням поставлених проблем, які пов’язані зі Streamer.Bot.
Головні концепції, які слід пам’ятати при написанні коду:
Коментуйте код, час від часу, щоб пригадати те, що ви хотіли написати.
Використовуйте команду Compile, щоб перевірити наявність/відстутність помилок.
Використовуйте логи, щоб намагатися зрозуміти, де саме знаходиться помилка.
Більше практикуйтесь. Програмування - це практична наука. Теорія без практики буде безкорисна
Не забувайте, що методи виводу у логи чи в чат, ми використовуємо текст, а не числа
Корисні посилання
➕ Офіційна документація C# для SB: https://docs.streamer.bot/api/csharp/guide/intro
➕ Список всіх CPH методів: https://docs.streamer.bot/api/csharp/methods
➕ Execute C# Code Sub-Action: https://docs.streamer.bot/api/sub-actions/core/csharp/execute-csharp-code
➕ C# для початківців: https://w3schoolsua.github.io/cs/index.html#gsc.tab=0
➕ Стаття про змінні в SB: https://drukarnia.com.ua/articles/streamer-bot-zminni-XP2qv
➕ Стаття про Sub-Actions: https://drukarnia.com.ua/articles/streamer-bot-sho-take-sub-actions-Xp1gD
➕ Стаття про тригери: https://drukarnia.com.ua/articles/streamer-bot-sho-take-trigeri-fypMP
💜 Мій Twitch канал: https://www.twitch.tv/quarryck
🥰 Підписатись на канал Streamer.BotUA: https://t.me/StreamBotUA
🫂 Платна підписка на автора: https://base.monobank.ua/quarryck
💴 Донат: https://send.monobank.ua/jar/9mvkm2Hy2z
❔Питання до автора в Телеграм чаті по Streamer.Bot: https://t.me/+MExWZc41vR5mMDAy
❔Питання до автора в Discord чаті по Streamer.Bot: https://discord.gg/9pVEtS24cU