Друкарня від WE.UA

Streamer.Bot. Програмування

Зміст

Комплексна тема, але не менш цікава. Можу вас запевнити, якщо у вас ніколи не було досвіду з написанням коду, це не так складно, як здається. Я спробую максимально просто і доступно пояснити про програмування на мові 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

Спробуйте автоматично знайти деякі загальні посилання на основі ваших директив using які ви використовуєте.

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 або -123

  • double - зберігає числа з плаваючою комою з десятковими дробами, наприклад 19,99 або -19.99

  • char - зберігає окремі символи, такі як '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. Як це виправити? Є кілька варіантів:

  1. Конкатенація з текстом:

    int points = 100;
    CPH.LogInfo("Кількість балів: " + points);  // ✅ Працює

    Коли ви додаєте число до тексту через +, C# автоматично перетворює число в текст.

  2. Метод .ToString() Цей метод здатен перетворювати будь-який тип даних в текст.

    int points = 100;
    CPH.LogInfo(points.ToString());  // ✅ Працює
  3. Інтерполяція рядків

    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

null

4

null


Ми можемо створювати їх ще так. У такому випадку масив створюється з елементами, програма визначає, що розмір такого масиву - 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?

Примітка. Для нашої роботи це не має значення, адже, що списки, що масиви, в нашому випадку будуть виконувати свою роботу за мілісекунди, тому пункт про масиви можна було пропустити, але це фундаментальний розділ в програмуванні. Для написання скриптів, ми будемо користуватись Списками.

Таблиця корисних методів для списків:

Метод / властивість

Що робить

Приклад

Add(item)

Додає елемент в кінець

list.Add(5);

AddRange(col)

Додає колекцію

list.AddRange(otherList);

Remove(item)

Видаляє перше входження

list.Remove(5);

RemoveAt(index)

Видаляє за індексом

list.RemoveAt(0);

RemoveAll(pred)

Видаляє за умовою

list.RemoveAll(x => x < 0);

Clear()

Очищає список

list.Clear();

Contains(item)

Перевіряє наявність

list.Contains(5);

IndexOf(item)

Індекс елемента

list.IndexOf(5);

Count

Кількість елементів

list.Count

Capacity

Виділена памʼять

list.Capacity

Sort()

Сортує список

list.Sort();

Reverse()

Розвертає

list.Reverse();

Find(pred)

Перший елемент за умовою

list.Find(x => x > 10);

FindAll(pred)

Всі елементи за умовою

list.FindAll(x => x > 10);

Exists(pred)

Чи є хоча б один

list.Exists(x => x == 0);

ForEach(action)

Дія для кожного

list.ForEach(Console.WriteLine);

ToArray()

Перетворює в масив

int[] arr = list.ToArray();

Це основне в програмуванні, що треба знати вам для того, щоб писати скрипти або навіть програми. Я дуже рекомендую використати цей сайт: 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.Bothttps://discord.gg/9pVEtS24cU

Статті про вітчизняний бізнес та цікавих людей:

Поділись своїми ідеями в новій публікації.
Ми чекаємо саме на твій довгочит!
Quarryck
Quarryck@quarryck we.ua/quarryck

Стример на платформi Twitch

6Довгочити
65Прочитання
3Підписники
На Друкарні з 5 грудня

Більше від автора

  • Streamer.Bot. Налаштування OBS

    Привіт! Розглянемо те, як підключити Streamer.Bot до OBS. Спробуємо здійснити керування OBS через Streamer.Bot та зробимо кілька прикладів.

    Теми цього довгочиту:

    Twitch
  • Streamer.bot. Що таке Sub-Actions?

    У попередніх статтях ми розібрали, що таке Streamer.bot, як створювати команди та працювати з тригерами. Сьогодні поговоримо про найцікавіше — Sub-Actions. Я наведу кілька прикладів їх використання і як в попередньому разі, постараюсь виділити основні, якими варто користуватись.

    Теми цього довгочиту:

    Twitch
  • Streamer.bot. Змінні

    Змінна – це ім’я, яке використовується для зберігання та звернення до даних. Вони різні за іменем і мають різне значення. Вони здатні зберігати ім'я користувача, кількість балів, текст повідомлення тощо.

    Теми цього довгочиту:

    Twitch

Це також може зацікавити:

Коментарі (0)

Підтримайте автора першим.
Напишіть коментар!

Це також може зацікавити: