Skip to content

UO Topic http

Codex edited this page Oct 11, 2026 · 6 revisions

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

HTTP-запити та зовнішні повідомлення

Головна · C# · IDE · Команди UO · За абеткою · Приклади · Мови

Надсилання HTTP-запитів і читання відповіді: коду стану, заголовків та тексту. Для повідомлень у Telegram, Discord і Viber є команда Messenger.

Розділи

Тема Команди та пояснення
GET-запит UO.HTTP_Get
POST-запит UO.HTTP_Post
Заголовки відповіді UO.HTTP_Header
Текст відповіді UO.HTTP_Body
Зовнішні повідомлення UO.Messenger - Telegram, Discord та Viber

Усі команди теми

HTTP-запити

UO.HTTP_Get · UO.HTTP_Post · UO.HTTP_Header · UO.HTTP_Body

Приклади на тему

Нижче наведено короткі приклади. У повному описі кожної команди є параметри, результат, обмеження та кілька самостійних скриптів: прямий код, варіант із функцією та варіант із класом.

UO.HTTP_Get

Параметри, результат та всі сценарії

UO.HTTP_Get("https://example.com/csharp-config.json");
try
{
    string body = Convert.ToString(UO.HTTP_Body()) ?? "";
    using (var document = System.Text.Json.JsonDocument.Parse(body))
    {
        if (document.RootElement.TryGetProperty("minMana", out var value) &&
            value.TryGetInt32(out int threshold) && threshold is >= 0 and <= 100)
            return threshold;
    }
}
catch (System.Text.Json.JsonException)
{
    UO.Print("Response is not a valid configuration; using the default.");
}
return 30;

UO.HTTP_Body

Параметри, результат та всі сценарії

UO.HTTP_Get("https://example.com/C#-permission");
var permission = TrimText(UO.HTTP_Body());
return Truth(permission == "allow");

bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;

string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();

Повний опис команд


UO.HTTP_Body

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

dynamic UO.HTTP_Body();

Читає текст останнього HTTP-відповіді цього скрипта. Наприклад, після HTTP_Get можна розібрати JSON з налаштуваннями або порівняти відповідь свого сервісу з очікуваним рядком. Саме читання не звертається до мережі.

Параметри

Параметрів немає.

Повернене значення

string - збережений текст. До першого запиту цього runtime, після GET в потік і після мережевої помилки — порожній рядок. Порожнє тіло також буває у нормальної відповіді, наприклад HTTP 204. Не порівнюйте результат із true/false як ознака доставки.

Поведінка

  • Остання відповідь зберігається тільки в поточному скрипті runtime. Наступний GET/POST це runtime замінює його; інші одночасно працюючі скрипти його не змінюють. Відповідь не зберігається у профіль. Якщо він потрібен після наступного запиту, заздалегідь скопіюйте тіло та заголовки у змінні.
  • GET/POST чекають відповіді в потоці скрипту. Загальний термін запиту та читання тіла - 20 секунд. Зупинка скрипта скасовує очікування; HTTP_Body/HTTP_Header нічого не чекають. Все тіло завантажується в пам'ять навіть під час передачі FileStream; це не потокове завантаження великих файлів.
  • Текст декодується за charset відповіді, за відсутності/невідомого кодування - UTF-8. Відповіді HTTP 4xx/5xx також читаються. При мережній помилці або таймуут клієнт пише помилку, тіло та заголовки стають порожніми; Try/Catch не замінює перевірку очікуваної відповіді. Скасування скрипта поширюється далі. Помилка локального запису файлу або неправильного аргументу може бути перехоплена Try/Catch.
  • HTTP_Body тільки читає останній буфер: не повторює запит, не очищає відповідь та не видає дані іншого скрипту. Після двійкового GET використовуйте MemoryStream.ToArray() або збережений файл, а не цей текстовий буфер.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

UO.HTTP_Get("https://example.com/");
object? result = UO.HTTP_Body();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));

1. Дозволити дію лише за очікуваного тексту — прямий скрипт

Параметри та порядок виконання:

  • Сервіс повинен повернути allow. Інша відповідь, включаючи порожню, дає false. Приклад лише обчислює дозвіл; не запускає рух чи бій.
  • Адреси example.com ілюстративні та не надають такий сервіс. Замініть їх своїми; запуск прикладу робить реальний HTTP-запит. Ігрових дій приклад не виконує.
UO.HTTP_Get("https://example.com/C#-permission");
var permission = TrimText(UO.HTTP_Body());
return Truth(permission == "allow");

bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;

string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();

2. Зібрати опис із двох відповідей — функція сценарію

Параметри та порядок виконання:

  • Спочатку зберігається назва маршруту, потім запитується опис. Без routeName другий GET замінив би першу відповідь.
  • Адреси example.com ілюстративні та не надають такий сервіс. Замініть їх своїми; запуск прикладу робить реальний HTTP-запит. Ігрових дій приклад не виконує.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
    UO.HTTP_Get("https://example.com/route-name");
    var routeName = UO.HTTP_Body();
    UO.HTTP_Get("https://example.com/route-description");
    return routeName + ": " + UO.HTTP_Body();
    return null;
}

3. Відокремити бінарний потік від текстового буфера – клас сценарію.

Параметри та порядок виконання:

  • Після GET з System.IO.MemoryStream байти знаходяться в потоці, а HTTP_Body порожній. Це діє і для коректної бінарної відповіді; порожній текст означає відсутність байтів.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
    private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
    private readonly Func<int, Task> WaitAsync;
    private readonly string[] Args;
    private readonly CancellationToken Cancellation;
    private readonly Action Checkpoint;
    public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
    {
        UO = api;
        WaitAsync = wait;
        Args = args;
        Cancellation = cancellation;
        Checkpoint = checkpoint;
    }

    async public Task<object?> RunScenarioAsync()
    {
        using (var data = new System.IO.MemoryStream())
        {
            UO.HTTP_Get("https://example.com/route-data.bin", data);
            string body = Convert.ToString(UO.HTTP_Body()) ?? "";
            UO.Print($"Binary bytes: {data.Length}; text-body characters: {body.Length}");
            return body;
        }

        return null;
    }
}

UO.HTTP_Get

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

void UO.HTTP_Get(object? arg0);
void UO.HTTP_Get(object? arg0, object? arg1);

Завантажує дані по HTTP/HTTPS. Підходить для читання налаштувань зі свого сервісу чи отримання файлу; не керує ігровим підключенням та не запускає завантажений код.

Параметри

  • URL — Обов'язкова string: повна адреса http:// або https://. Замініть example.com на адресу свого сервісу. Гра та ігровий сервер для цього запиту не потрібні; використовується звичайне мережне підключення процесу, а не ігровий проксі профілю.
  • LStream – необов'язковий стандартний .NET System.IO.Stream, доступний для запису: наприклад new System.IO.MemoryStream() або System.IO.File.Create(path). Без нього або з 0/null текст читається HTTP_Body(). Потік отримує вихідні байти. Для seekable-потоку колишній вміст обнулюється, а позиція до та після запису стає 0; non-seekable-потік отримує запис у поточну позицію. Створення FileStream через File.Create обнулює файл відразу; батьківський каталог має існувати. Невідповідний аргумент чи потік лише для читання відхиляється до запиту.

Повернене значення

void - значення, що повертається немає. Викликайте окремим рядком; результат не можна використовувати як bool, ID або кількість байтів. Текст після звичайного запиту читається HTTP_Body(), двійкові дані з переданого потоку.

Поведінка

  • Остання відповідь зберігається тільки в поточному скрипті runtime. Наступний GET/POST це runtime замінює його; інші одночасно працюючі скрипти його не змінюють. Відповідь не зберігається у профіль. Якщо він потрібен після наступного запиту, заздалегідь скопіюйте тіло та заголовки у змінні.
  • GET/POST чекають відповіді в потоці скрипту. Загальний термін запиту та читання тіла - 20 секунд. Зупинка скрипта скасовує очікування; HTTP_Body/HTTP_Header нічого не чекають. Все тіло завантажується в пам'ять навіть під час передачі FileStream; це не потокове завантаження великих файлів.
  • Текст декодується за charset відповіді, за відсутності/невідомого кодування - UTF-8. Відповіді HTTP 4xx/5xx також читаються. При мережній помилці або таймуут клієнт пише помилку, тіло та заголовки стають порожніми; Try/Catch не замінює перевірку очікуваної відповіді. Скасування скрипта поширюється далі. Помилка локального запису файлу або неправильного аргументу може бути перехоплена Try/Catch.
  • GET без потоку оновлює текст та заголовки. GET з потоком записує байти, очищає HTTP_Body та зберігає заголовки. Навіть порожня відповідь/мережева помилка замінюють вміст потоку порожніми даними: для збереження попереднього файлу спочатку скачайте в MemoryStream і перевірте дані.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Команда викликається окремим рядком. Повідомлення перед нею показує початок виклику, а не підтвердження дії сервера.

UO.Print("Calling UO.HTTP_Get");
UO.HTTP_Get("https://example.com/");

1. Прочитати JSON-конфігурацію з перевіркою діапазону - прямий скрипт

Параметри та порядок виконання:

  • example.com - демонстраційна адреса; замініть його своїм. System.Text.Json читає тіло відповіді і приймає тільки ціле minMana від 0 до 100. Порожній/неправильний JSON дає значення за замовчуванням 30.
UO.HTTP_Get("https://example.com/csharp-config.json");
try
{
    string body = Convert.ToString(UO.HTTP_Body()) ?? "";
    using (var document = System.Text.Json.JsonDocument.Parse(body))
    {
        if (document.RootElement.TryGetProperty("minMana", out var value) &&
            value.TryGetInt32(out int threshold) && threshold is >= 0 and <= 100)
            return threshold;
    }
}
catch (System.Text.Json.JsonException)
{
    UO.Print("Response is not a valid configuration; using the default.");
}
return 30;

2. Перевірити бінарні байти перед збереженням файлу – функція сценарію

Параметри та порядок виконання:

  • Передається стандартний System.IO.MemoryStream. Він отримує оригінальні байти відповіді; HTTP_Body стає порожнім. Існуючий download.bin замінюється лише після отримання непустих даних. Перевірка довжини не доводить правильність вмісту.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
    using (var data = new System.IO.MemoryStream())
    {
        UO.HTTP_Get("https://example.com/route-data.bin", data);
        if (data.Length == 0)
        {
            UO.Print("The response is empty; no file was written.");
            return false;
        }

        System.IO.File.WriteAllBytes("download.bin", data.ToArray());
        return true;
    }

    return null;
}

3. Завантажити бінарну відповідь прямо в FileStream — клас сценарію

Параметри та порядок виконання:

  • System.IO.File.Create створює або відразу обнуляє файл; GET записує вихідні байти. Якщо пуста відповідь, файл залишиться порожнім. Для збереження попередньої версії спочатку використовуйте MemoryStream, як у попередньому сценарії. using закриває потік.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
    private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
    private readonly Func<int, Task> WaitAsync;
    private readonly string[] Args;
    private readonly CancellationToken Cancellation;
    private readonly Action Checkpoint;
    public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
    {
        UO = api;
        WaitAsync = wait;
        Args = args;
        Cancellation = cancellation;
        Checkpoint = checkpoint;
    }

    async public Task<object?> RunScenarioAsync()
    {
        using (var output = System.IO.File.Create("http-download.bin"))
        {
            UO.HTTP_Get("https://example.com/route-data.bin", output);
        }

        return UO.HTTP_Header();
        return null;
    }
}

UO.HTTP_Header

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

dynamic UO.HTTP_Header();

Читає заголовки останнього HTTP-відповіді цього скрипту: наприклад Content-Type, щоб дізнатися заявлений формат даних. Це не тіло відповіді, не заголовки запиту та не числовий код HTTP.

Параметри

Параметрів немає.

Повернене значення

string — рядки виду Ім'я: значення, розділені CRLF. До першого запиту та після мережевої помилки – порожній рядок. Рядки HTTP/1.1 200 OK тут немає; код стану не представлений окремою командою. Порядок та регістр імен не гарантовано.

Поведінка

  • Остання відповідь зберігається тільки в поточному скрипті runtime. Наступний GET/POST це runtime замінює його; інші одночасно працюючі скрипти його не змінюють. Відповідь не зберігається у профіль. Якщо він потрібен після наступного запиту, заздалегідь скопіюйте тіло та заголовки у змінні.
  • GET/POST чекають відповіді в потоці скрипту. Загальний термін запиту та читання тіла - 20 секунд. Зупинка скрипта скасовує очікування; HTTP_Body/HTTP_Header нічого не чекають. Все тіло завантажується в пам'ять навіть під час передачі FileStream; це не потокове завантаження великих файлів.
  • Текст декодується за charset відповіді, за відсутності/невідомого кодування - UTF-8. Відповіді HTTP 4xx/5xx також читаються. При мережній помилці або таймуут клієнт пише помилку, тіло та заголовки стають порожніми; Try/Catch не замінює перевірку очікуваної відповіді. Скасування скрипта поширюється далі. Помилка локального запису файлу або неправильного аргументу може бути перехоплена Try/Catch.
  • HTTP_Header поєднує заголовки відповіді та її вмісту. Після двійкового GET вони також доступні. Перевіряти ім'я слід без урахування регістру. Content-Type – заява сервера, а не перевірка вмісту; не виконуйте завантажений текст як код.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

UO.HTTP_Get("https://example.com/");
object? result = UO.HTTP_Header();
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));

1. Прочитати заголовок відповіді без залежності від регістру – прямий скрипт

Параметри та порядок виконання:

  • Заголовки розбираються рядками. Ім'я Content-Type порівнюється без урахування регістру; за відсутності рядка повертається порожній рядок.
UO.HTTP_Get("https://example.com/csharp-status");
return ReadHeader(Convert.ToString(UO.HTTP_Header()) ?? "", "Content-Type");

string ReadHeader(string headers, string name)
{
    foreach (string line in headers.Split(new[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries))
    {
        int separator = line.IndexOf(':');
        if (separator > 0 && line[..separator].Trim().Equals(name, StringComparison.OrdinalIgnoreCase))
            return line[(separator + 1)..].Trim();
    }
    return "";
}

2. Перевірити оголошений JSON Content-Type — функція сценарію

Параметри та порядок виконання:

  • Перевіряється локально збережений текст заголовків. Content-Type сам по собі не гарантує правильність JSON; Вміст окремо перевіряйте System.Text.Json.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
    UO.HTTP_Get("https://example.com/csharp-status");
    string headers = Convert.ToString(UO.HTTP_Header()) ?? "";
    return headers.Contains("application/json", StringComparison.OrdinalIgnoreCase);
    return null;
}

3. Зберегти заголовки бінарної відповіді – клас сценарію

Параметри та порядок виконання:

  • GET спрямовує вихідні байти в System.IO.MemoryStream. Заголовки останньої відповіді, як і раніше, читаються HTTP_Header; текстовий HTTP_Body для цієї форми порожній. У файл зберігаються лише заголовки.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
    private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
    private readonly Func<int, Task> WaitAsync;
    private readonly string[] Args;
    private readonly CancellationToken Cancellation;
    private readonly Action Checkpoint;
    public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
    {
        UO = api;
        WaitAsync = wait;
        Args = args;
        Cancellation = cancellation;
        Checkpoint = checkpoint;
    }

    async public Task<object?> RunScenarioAsync()
    {
        using (var data = new System.IO.MemoryStream())
        {
            UO.HTTP_Get("https://example.com/route-data.bin", data);
            string headers = Convert.ToString(UO.HTTP_Header()) ?? "";
            System.IO.File.WriteAllText("http-response-headers.txt", headers);
            UO.Print($"Saved response headers; downloaded {data.Length} binary bytes.");
            return headers;
        }

        return null;
    }
}

UO.HTTP_Post

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

dynamic UO.HTTP_Post(object? arg0, object? arg1);

Відправляє текст своєму HTTP-сервісу методом POST та повертає текст відповіді. Наприклад, скрипт може передати звіт про зупинку маршруту. Це не готова команда Telegram/Discord: їх протокол, авторизація та формат запиту потребують окремої підтримки.

Параметри

  • URL — Обов'язкова string: повна адреса http:// або https://. Замініть example.com на адресу свого сервісу. Гра та ігровий сервер для цього запиту не потрібні; використовується звичайне мережне підключення процесу, а не ігровий проксі профілю.
  • PostData — Обов'язкова string з тілом запиту. Надсилається UTF-8 з Content-Type: text/plain; charset=utf-8. Немає автоматичного кодування форми та перемикання на application/json. System.Text.Json.JsonSerializer.Serialize лише формує текст: сервер прикладу повинен приймати JSON саме як text/plain. Налаштувати довільні заголовки цими командами не можна.

Повернене значення

string - текст відповіді; він доступний через HTTP_Body(). Це не bool і не код HTTP. Порожній рядок не доводить помилку, а непустий — успіх операції на сервері.

Поведінка

  • Остання відповідь зберігається тільки в поточному скрипті runtime. Наступний GET/POST це runtime замінює його; інші одночасно працюючі скрипти його не змінюють. Відповідь не зберігається у профіль. Якщо він потрібен після наступного запиту, заздалегідь скопіюйте тіло та заголовки у змінні.
  • GET/POST чекають відповіді в потоці скрипту. Загальний термін запиту та читання тіла - 20 секунд. Зупинка скрипта скасовує очікування; HTTP_Body/HTTP_Header нічого не чекають. Все тіло завантажується в пам'ять навіть під час передачі FileStream; це не потокове завантаження великих файлів.
  • Текст декодується за charset відповіді, за відсутності/невідомого кодування - UTF-8. Відповіді HTTP 4xx/5xx також читаються. При мережній помилці або таймуут клієнт пише помилку, тіло та заголовки стають порожніми; Try/Catch не замінює перевірку очікуваної відповіді. Скасування скрипта поширюється далі. Помилка локального запису файлу або неправильного аргументу може бути перехоплена Try/Catch.
  • POST оновлює тіло та заголовки та повертає те ж тіло рядком. Не повторюйте POST автоматично лише через порожню відповідь: сервер міг уже виконати дію. Перевірка accepted/status у прикладах — домовленість із вашим сервісом, не вбудована ознака HTTP-успіху.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

Результат одного виклику виводиться в журнал. Число не перетворюється на bool; для масиву показано кількість елементів.

object? result = UO.HTTP_Post("https://example.com/", "Hello from C#");
UO.Print(result is Array values ? "Count: " + values.Length : Convert.ToString(result));

1. Перевірити домовлену відповідь сервісу — прямий скрипт

Параметри та порядок виконання:

  • Сервіс приймає текст Route stopped та за домовленістю відповідає accepted. Main повертає true тільки за такого тексту; це перевірка протоколу вашого сервісу, не перевірка HTTP-коду.
  • Адреси example.com ілюстративні та не надають такий сервіс. Замініть їх своїми; запуск прикладу робить реальний HTTP-запит. Ігрових дій приклад не виконує.
var reply = UO.HTTP_Post("https://example.com/C#-event", "Route stopped");
return Truth(TrimText(reply) == "accepted");

bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;

string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();

2. Надіслати серіалізовану JSON та розібрати JSON-відповідь — функція сценарію

Параметри та порядок виконання:

  • System.Text.Json.JsonSerializer екранує рядки словника. Значення status читається після перевірки JSON; демонстраційну адресу замініть своєю.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
    var report = new Dictionary<string, string>
    {
        ["event"] = "route-stopped",
        ["text"] = "line one\nline two"
    };
    string payload = System.Text.Json.JsonSerializer.Serialize(report);
    string reply = Convert.ToString(UO.HTTP_Post("https://example.com/csharp-report", payload)) ?? "";
    try
    {
        using (var document = System.Text.Json.JsonDocument.Parse(reply))
        {
            return document.RootElement.TryGetProperty("status", out var value) ? value.GetString() : "unknown";
        }
    }
    catch (System.Text.Json.JsonException)
    {
        return "invalid response";
    }

    return null;
}

3. Зберегти відповідь до наступного запиту - клас сценарію

Параметри та порядок виконання:

  • firstReply та firstHeaders зберігають відповідь POST. Наступний GET замінює внутрішні буфери, але локальні змінні, як і раніше, містять першу відповідь.
  • Адреси example.com ілюстративні та не надають такий сервіс. Замініть їх своїми; запуск прикладу робить реальний HTTP-запит. Ігрових дій приклад не виконує.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
    private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
    private readonly Func<int, Task> WaitAsync;
    private readonly string[] Args;
    private readonly CancellationToken Cancellation;
    private readonly Action Checkpoint;
    public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
    {
        UO = api;
        WaitAsync = wait;
        Args = args;
        Cancellation = cancellation;
        Checkpoint = checkpoint;
    }

    async public Task<object?> RunScenarioAsync()
    {
        var firstReply = UO.HTTP_Post("https://example.com/C#-event", "Route stopped");
        var firstHeaders = UO.HTTP_Header();
        UO.HTTP_Get("https://example.com/C#-status");
        return firstReply + "|" + firstHeaders;
        return null;
    }
}

UO.Messenger

Українська · Русский · English · Deutsch · Français · Italiano · Español · 繁體中文 · 日本語 · 한국어

C#-сигнатури

dynamic UO.Messenger(object? arg0);

Створює об'єкт для текстових повідомлень та отримання повідомлень Telegram, Discord або Viber. Наприклад, скрипт може повідомити про закінчення збору ресурсів або перевірити запит зупинки від вказаного користувача. Створення об'єкта ще не підключає робота і нічого не відправляє.

Параметри

  • provider - string: "telegram", "discord" або "viber"; регістр не важливий. Інші значення викликають помилку.

Повернене значення

Object Messenger. Це не bool і не ID. ID повідомлень, відправників і чатів у цьому об'єкті завжди string: порівнюйте їх з рядками, не перетворюйте через Convert.ToInt32/Convert.ToDouble.

Поведінка

  • Provider() → string; Connected() → 1/0 (true/false): постачальник та результат останньої перевірки авторизації. Connected не гарантує доступність Інтернету цієї секунди.
  • Connect(token) → null: перевіряє токен бота; ConnectFromFile(path) → null: читає токен UTF-8 з файлу до 1024 байт. Відносний шлях вважається від поточного папки скрипта. Повторне підключення вимагає Disconnect. Помилки можна перехопити Try/Catch.
  • Disconnect() → null: припиняє локальний прийом, очищує токен та курсори; об'єкт можна знову підключити. Dispose() → null: закриває об'єкт остаточно.
  • SendMessage(text, recipient) → string: ID прийнятого повідомлення. Параметри - текст і рядковий chat ID Telegram, channel ID Discord або ID передплатника Viber. Ліміти довжини: 4096/2000/7000 відповідно; також Viber JSON ≤30000 байт. Порожній текст заборонено. Discord не створює згадки everyone/ролей.
  • WatchChannel(channelId) → null: Discord, запам'ятовує поточне останнє повідомлення та читає лише наступні. WatchChannel(channelId, afterMessageId) → null: починає після заданого рядкового ID; "0" включає історію. До 32 каналів на об'єкт.
  • Receive(timeoutSeconds) → Array; Receive(): таймойт 0. Діапазон 0..20 секунд; пустий масив означає відсутність доступних текстових повідомлень. Telegram використовує long polling, Discord опитує вибрані канали, Viber читає чергу webhook. Запит може зайняти до 30 секунд.
  • Кожен «MessengerMessage»: «Id()», «SenderId()», «SenderName()», «ChatId()», «Text()» → string. Поста Telegram від каналу може не бути SenderId. Вкладення, нетекстові події та повідомлення Discord від роботів не повертаються.
  • RetryAfter() → int: скільки секунд чекати після обмеження сервісу. До закінчення цього терміну нові HTTP-запити не виконуються. Надсилання після збою не повторюється автоматично: сервер міг уже прийняти повідомлення.
  • StartReceiver(localPort, publicHttpsUrl) → int: тільки Viber; порт 1..65535, повертає зайнятий локальний порт. Публічна HTTPS-адреса повинна закінчуватися /viber/ і заздалегідь пересилати POST на 127.0.0.1:порт/viber/ з вихідним тілом та заголовком підпису. Метод реєструє webhook у Viber.
  • Потрібен токен бота, не пароль особистого облікового запису. Telegram з існуючим webhook відхиляється без його видалення. Discord вимагає прав читання/надсилання каналу та MESSAGE_CONTENT для доступного тексту; Viber відправляє користувачам, що підписалися.
  • Receive зберігає курсор лише після розбору всієї пачки. Telegram/Discord повертають до 100 записів за запит; викликайте Receive знову для наступних пачок. Discord без другого аргументу WatchChannel пропускає стару історію.
  • Viber перевіряє HMAC-SHA256 вихідного тіла. Черга - 100 повідомлень, повторні ID зберігаються для останніх 2048 доставок; переповнення дає HTTP 503 для повтору сервісом. Потрібен HTTPS-проксі з Content-Length; chunked-запити на локальному вході відхиляються.
  • Токен не записується у профіль, текст помилок та історію аргументів Connect. Використовуйте ConnectFromFile, щоб не зберігати його в змінних скриптах, видимих ​​відладчику. Не публікуйте файли токенів.
  • Створюйте об'єкт усередині процедури. Не більше 32 одночасно; Using/Dispose звільняє його раніше. При завершенні, помилці або зупинці скрипту всі його messenger-об'єкти закриваються. Закриття Viber-приймача не видаляє webhook у сервісу.
  • Це текстовий інтерфейс: він не виконує отриманий текст як код і не підключає ігрові облікові записи. Умови довіри до відправника ставить сам скрипт.

Самостійні C#-скрипти

Кожен приклад можна зберегти окремим файлом .csx та запускати в IDE. Об'єкт UO та функції очікування надає host поточної ігрової сесії. Демонстраційні serial, імена, координати та адреси замініть своїми.

Простий приклад

Виконайте цей код як окремий файл .csx. Аргументи видно безпосередньо у виклику; демонстраційні імена, serial та адреси замініть своїми.

dynamic messenger = UO.Messenger("telegram");
UO.Print(messenger.Provider());
messenger.Dispose();

1. Telegram: повідомлення після завершення роботи – прямий скрипт

Параметри та порядок виконання:

  • Покладіть telegram-token.txt поряд зі скриптом, замініть 12345678 на свій chat ID. Приклад відправляє одне повідомлення та повертає рядковий ID; отримання відповіді сервера не підтверджує прочитання людиною.
  • Вам потрібні власні налаштування бота. Приклади перевіряються локальними тестовими відповідями; вони не були надіслані реальним користувачам.
var bot = UO.Messenger("telegram");
using (var resource = bot)
{
    bot.ConnectFromFile("telegram-token.txt");
    var messageId = bot.SendMessage("Harvest finished", "12345678");
    return messageId;
}

2. Discord: запит зупинки від вибраного користувача – функція сценарію

Параметри та порядок виконання:

  • Вкажіть свій канал і ID дозволеного відправника. true означає, що за цю перевірку надійшов текст stop від нього; сам приклад не зупиняє рух. Цей результат можна використовувати за умови власного робочого циклу.
  • Вам потрібні власні налаштування бота. Приклади перевіряються локальними тестовими відповідями; вони не були надіслані реальним користувачам.
return await RunScenarioAsync();
async Task<object?> RunScenarioAsync()
{
    var bot = UO.Messenger("discord");
    using (var resource = bot)
    {
        bot.ConnectFromFile("discord-token.txt");
        bot.WatchChannel("123456789012345678");
        var messages = bot.Receive(5);
        foreach (var message in messages)
        {
            if (Truth(message.SenderId() == "987654321098765432") && Truth(Convert.ToString(TrimText(message.Text())) == "stop"))
            {
                return true;
            }
        }

        return false;
    }

    return null;
}

bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
string TrimText(object? value) => (Convert.ToString(value) ?? "").Trim();

3. Завантажити налаштування приймача з JSON-файлу - клас сценарію

Параметри та порядок виконання:

  • System.Text.Json читає локальний port/publicUrl. Токен зберігається в окремому локальному файлі; реальні відправки не виконуються цим прикладом. Перевіряється довірений SenderId, а не довільний вхідний текст.
return await new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenarioAsync();
class ScriptScenario
{
    private readonly global::ClassicUO.CSharp.CSharpGameApi UO;
    private readonly Func<int, Task> WaitAsync;
    private readonly string[] Args;
    private readonly CancellationToken Cancellation;
    private readonly Action Checkpoint;
    public ScriptScenario(global::ClassicUO.CSharp.CSharpGameApi api, Func<int, Task> wait, string[] args, CancellationToken cancellation, Action checkpoint)
    {
        UO = api;
        WaitAsync = wait;
        Args = args;
        Cancellation = cancellation;
        Checkpoint = checkpoint;
    }

    async public Task<object?> RunScenarioAsync()
    {
        var settingsDocument = System.Text.Json.JsonDocument.Parse(System.IO.File.ReadAllText("viber-settings.json"));
        using (settingsDocument)
        {
            var settings = settingsDocument.RootElement;
            var bot = UO.Messenger("viber");
            using (var resource = bot)
            {
                bot.ConnectFromFile("viber-token.txt");
                bot.StartReceiver(settings.GetProperty("port").GetInt32(), settings.GetProperty("publicUrl").GetString());
                var messages = bot.Receive(5);
                foreach (var message in messages)
                {
                    if (Truth(message.SenderId() == "trusted-subscriber-id"))
                    {
                        return message.Text();
                    }
                }

                return "";
            }
        }

        return null;
    }

    bool Truth(object? value) => value is bool flag ? flag : value is string text ? !string.IsNullOrEmpty(text) : value != null && Convert.ToDouble(value) != 0;
}

Clone this wiki locally