Skip to content

ZH TW UO Topic http

Codex edited this page Oct 12, 2026 · 4 revisions

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

HTTP

家 · C# · IDE · UO API · A–Z · 範例 · Languages

HTTP-查詢並讀取回應。狀態代碼、標頭和回應正文是單獨的資料。

部分

主題 命令與解釋
HTTP_Get UO.HTTP_Get
HTTP_Post UO.HTTP_Post
HTTP_Header UO.HTTP_Header
HTTP_Body 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 — 儲存的文字。在此運行時中的第一個請求之前、流中的GET之後以及網路錯誤之後 - 空行。正常的答案也有空的主體,例如 HTTP 204。請勿將結果與true/false 進行比較作為交付的指示。

行為

  • 最後的回應僅儲存在腳本的當前運行時。該運行時的下一個GET/POST將取代它;其他同時運行的腳本不會改變它。答案不會儲存到設定檔中。如果您在下一個請求後需要它,請提前將正文和標頭複製到變數中。
  • GET/POST 在執行腳本執行緒中等待回應。請求和讀取正文的總時間為20秒。停止腳本會取消等待; HTTP_Body/HTTP_Header 沒什麼期待。即使FileStream被傳輸,整個body也會被載入到記憶體中;這不是大檔案的串流下載。
  • 在缺少/未知編碼的情況下,文字根據回應的字元集進行解碼 - UTF-8。答案HTTP 4xx/5xx 也已閱讀。當網路錯誤或逾時時,用戶端寫入錯誤,body和headers變空; Try/Catch 不會取代對預期回應的檢查。腳本取消的範圍進一步擴大。 Try/Catch 可以擷取本機檔案寫入或無效參數錯誤。
  • HTTP_Body 只讀取最後一個緩衝區:它不會重複請求,不會清除回應,也不會從其他腳本傳回資料。在二進位 GET 之後,使用 MemoryStream.ToArray() 或儲存的文件,而不是此文字緩衝區。

獨立的 C# 腳本

每個範例都可以儲存為單獨的檔案.csx並在IDE中運行。 UO物件和等待函數提供當前遊戲會話的主機。將演示 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。僅允許使用預期文字進行操作 - 直接腳本

參數與執行流程:

  • 該服務必須返回允許。另一個答案(包括空答案)給出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  RunScenario();
 object? RunScenario()
{
    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  new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
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;
    }

     public object? RunScenario()
    {
        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;
    }
}

命令實作

C# 區分大小寫。請使用正確的 UO 名稱。數值旗標應與 0 比較;只有回傳型別為 bool 時才使用 bool。

UO.HTTP_Body() — UO.HTTP_Body()

參數: 沒有參數。

結果: dynamic / Any.

呼叫時:

內部實作程式碼,不能作為獨立腳本執行。

case "http_body": return new InjectionValue(httpBody);

UO.HTTP_Get

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

C# 簽章

void UO.HTTP_Get(object? url);
void UO.HTTP_Get(object? url, object? lStream);

在 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()。線程接收原始位元組。對於可查找流,先前的內容被重設為零,寫入前後的位置變成0;不可查找執行緒接收對目前位置的寫入。透過 File.Create 建立 FileStream 會立即使檔案無效;父目錄必須存在。不適當的參數或唯讀流在請求之前被拒絕。

傳回值

void - 無回傳值。使用單獨的線路撥打電話;結果不能用作 bool、ID 或位元組數。正常請求後的文字由 HTTP_Body() 讀取,二進位資料從傳輸的流中讀取。

行為

  • 最後的回應僅儲存在腳本的當前運行時。該運行時的下一個GET/POST將取代它;其他同時運行的腳本不會改變它。答案不會儲存到設定檔中。如果您在下一個請求後需要它,請提前將正文和標頭複製到變數中。
  • GET/POST 在執行腳本執行緒中等待回應。請求和讀取正文的總時間為20秒。停止腳本會取消等待; HTTP_Body/HTTP_Header 沒什麼期待。即使FileStream被傳輸,整個body也會被載入到記憶體中;這不是大檔案的串流下載。
  • 在缺少/未知編碼的情況下,文字根據回應的字元集進行解碼 - UTF-8。答案HTTP 4xx/5xx 也已閱讀。當網路錯誤或逾時時,用戶端寫入錯誤,body和headers變空; Try/Catch 不會取代對預期回應的檢查。腳本取消的範圍進一步擴大。 Try/Catch 可以擷取本機檔案寫入或無效參數錯誤。
  • GET 無線程更新文字和標題。 GET 使用流寫入字節,清除 HTTP_Body 並儲存標頭。即使是空響應/網路錯誤也會用空資料取代流的內容:要保存舊文件,首先下載到MemoryStream並檢查資料。

獨立的 C# 腳本

每個範例都可以儲存為單獨的檔案.csx並在IDE中運行。 UO物件和等待函數提供當前遊戲會話的主機。將演示 serial 名稱、座標和地址替換為您自己的。

簡單範例

將這段程式碼存為獨立的 .csx 檔案執行。參數直接出現在呼叫中;請將範例名稱、serial 和網址替換成自己的值。

指令是獨立的陳述式。前面的訊息表示呼叫開始,並非伺服器已完成動作的確認。

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

1。讀取JSON-帶範圍檢查的配置-直接腳本

參數與執行流程:

  • example.com - 演示地址;用你的替換它。 System.Text.Json 讀取回應正文,僅接受 0 到 100 的整數 minMana。空/無效的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  RunScenario();
 object? RunScenario()
{
    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。使用關閉流。
return  new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
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;
    }

     public object? RunScenario()
    {
        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;
    }
}

命令實作

C# 區分大小寫。請使用正確的 UO 名稱。數值旗標應與 0 比較;只有回傳型別為 bool 時才使用 bool。

UO.HTTP_Get(url) — UO.HTTP_Get(Any)

參數: url (Any)

結果: void / Unit.

呼叫時:

內部實作程式碼,不能作為獨立腳本執行。

case "http_get":

                {

                    bool hasStream = arguments.Length > 1

                        && !(arguments[1].Kind == InjectionValueKind.Integer && arguments[1].Integer == 0)

                        && arguments[1].Kind != InjectionValueKind.Unit;

                    // Validate before network side effects and before changing the last response.

                    if (hasStream && !(arguments[1].Object is MemoryStreamObject))

                        throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream, 0, or omitted.");



                    string[] response = bridge.HttpRequest("GET", Text(0), string.Empty);

                    httpHeader = response.Length > 1 ? response[1] : string.Empty;

                    httpBody = hasStream ? string.Empty : response.Length > 0 ? response[0] : string.Empty;

                    if (!hasStream)

                    {

                        return InjectionValue.Unit;

                    }



                    byte[] raw = response.Length > 3 && !string.IsNullOrEmpty(response[3])

                        ? Convert.FromBase64String(response[3])

                        : Array.Empty<byte>();

                    if (arguments[1].Object is MemoryStreamObject memoryStream)

                        memoryStream.ReplaceBytes(raw);

                    else

                        throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream.");



                    // Stream overloads keep the response as bytes, not cached text.

                    return InjectionValue.Unit;

                }

UO.HTTP_Get(url, lStream) — UO.HTTP_Get(Any,Any)

參數: url (Any), lStream (Any)

結果: void / Unit.

呼叫時:

內部實作程式碼,不能作為獨立腳本執行。

if (name == "HTTP_Get" && arguments.Length == 2 && arguments[1] is Stream stream)
            {
                if (!stream.CanWrite) throw new ArgumentException("HTTP_Get requires a writable .NET stream.");
                // Adapt the existing binary response path without fetching the
                // response twice or converting its bytes through text encoding.
                var type = typeof(InjectionValue).Assembly.GetType("InjectionScript.Runtime.ObjectTypes.MemoryStreamObject", throwOnError: true)!;
                using var native = (IDisposable)Activator.CreateInstance(type, nonPublic: true)!;
                value = Invoke(name, [arguments[0], native]);
                var bytes = (InjectionValue)type.GetMethod("ToArray")!.Invoke(native, null)!;
                byte[] payload = bytes.Array.Select(item => checked((byte)item.Integer)).ToArray();
                if (stream.CanSeek) { stream.SetLength(0); stream.Position = 0; }
                stream.Write(payload);
                if (stream.CanSeek) stream.Position = 0;
            }
            else value = Invoke(name, arguments);

內部實作程式碼,不能作為獨立腳本執行。

case "http_get":

                {

                    bool hasStream = arguments.Length > 1

                        && !(arguments[1].Kind == InjectionValueKind.Integer && arguments[1].Integer == 0)

                        && arguments[1].Kind != InjectionValueKind.Unit;

                    // Validate before network side effects and before changing the last response.

                    if (hasStream && !(arguments[1].Object is MemoryStreamObject))

                        throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream, 0, or omitted.");



                    string[] response = bridge.HttpRequest("GET", Text(0), string.Empty);

                    httpHeader = response.Length > 1 ? response[1] : string.Empty;

                    httpBody = hasStream ? string.Empty : response.Length > 0 ? response[0] : string.Empty;

                    if (!hasStream)

                    {

                        return InjectionValue.Unit;

                    }



                    byte[] raw = response.Length > 3 && !string.IsNullOrEmpty(response[3])

                        ? Convert.FromBase64String(response[3])

                        : Array.Empty<byte>();

                    if (arguments[1].Object is MemoryStreamObject memoryStream)

                        memoryStream.ReplaceBytes(raw);

                    else

                        throw new NativeSubrutineException("UO.HTTP_Get: LStream must be a writable System.IO.Stream.");



                    // Stream overloads keep the response as bytes, not cached text.

                    return InjectionValue.Unit;

                }

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 行不在這裡;狀態代碼不由單獨的指令表示。不保證名稱的順序和大小寫。

行為

  • 最後的回應僅儲存在腳本的當前運行時。該運行時的下一個GET/POST將取代它;其他同時運行的腳本不會改變它。答案不會儲存到設定檔中。如果您在下一個請求後需要它,請提前將正文和標頭複製到變數中。
  • GET/POST 在執行腳本執行緒中等待回應。請求和讀取正文的總時間為20秒。停止腳本會取消等待; HTTP_Body/HTTP_Header 沒什麼期待。即使FileStream被傳輸,整個body也會被載入到記憶體中;這不是大檔案的串流下載。
  • 在缺少/未知編碼的情況下,文字根據回應的字元集進行解碼 - UTF-8。答案HTTP 4xx/5xx 也已閱讀。當網路錯誤或逾時時,用戶端寫入錯誤,body和headers變空; Try/Catch 不會取代對預期回應的檢查。腳本取消的範圍進一步擴大。 Try/Catch 可以擷取本機檔案寫入或無效參數錯誤。
  • HTTP_Header 結合了回應的標頭及其內容。在二進位GET之後它們也可用。應以不區分大小寫的方式檢查名稱。 Content-Type是伺服器聲明,不是內容檢查;不要將下載的文字當作程式碼執行。

獨立的 C# 腳本

每個範例都可以儲存為單獨的檔案.csx並在IDE中運行。 UO物件和等待函數提供當前遊戲會話的主機。將演示 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  RunScenario();
 object? RunScenario()
{
    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  new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
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;
    }

     public object? RunScenario()
    {
        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;
    }
}

命令實作

C# 區分大小寫。請使用正確的 UO 名稱。數值旗標應與 0 比較;只有回傳型別為 bool 時才使用 bool。

UO.HTTP_Header() — UO.HTTP_Header()

參數: 沒有參數。

結果: dynamic / Any.

呼叫時:

內部實作程式碼,不能作為獨立腳本執行。

case "http_header": return new InjectionValue(httpHeader);

UO.HTTP_Post

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

C# 簽章

dynamic UO.HTTP_Post(object? url, object? postData);

使用 POST 方法將文字傳送至其 HTTP 服務並回傳回應文字。例如,腳本可以報告路線停靠點。這不是現成的 Telegram/Discord 命令:它們的協定、授權和請求格式需要單獨的支援。

參數

  • url - 必需 string:完整地址 http:// 或 https://. 將 example.com 替換為您的服務地址。此請求不需要遊戲和遊戲伺服器;使用進程的正常網路連接,而不是遊戲代理設定檔。
  • postData — 強制 string 帶請求正文。由UTF-8發送,內容類型:text/plain;字符集=utf-8。沒有自動表單編碼並切換到 application/json。 System.Text.Json.JsonSerializer.Serialize 僅產生文字:範例伺服器應完全接受 JSON 作為文字/純文字。您無法使用這些命令配置自訂標頭。

傳回值

string — 响应文本;也可以通过 HTTP_Body() 访问它。这不是bool,也不是代码HTTP。空字串並不表示錯誤,但非空字串並不表示伺服器上的操作成功。

行為

  • 最後的回應僅儲存在腳本的當前運行時。該運行時的下一個GET/POST將取代它;其他同時運行的腳本不會改變它。答案不會儲存到設定檔中。如果您在下一個請求後需要它,請提前將正文和標頭複製到變數中。
  • GET/POST 在執行腳本執行緒中等待回應。請求和讀取正文的總時間為20秒。停止腳本會取消等待; HTTP_Body/HTTP_Header 沒什麼期待。即使FileStream被傳輸,整個body也會被載入到記憶體中;這不是大檔案的串流下載。
  • 在缺少/未知編碼的情況下,文字根據回應的字元集進行解碼 - UTF-8。答案HTTP 4xx/5xx 也已閱讀。當網路錯誤或逾時時,用戶端寫入錯誤,body和headers變空; Try/Catch 不會取代對預期回應的檢查。腳本取消的範圍進一步擴大。 Try/Catch 可以擷取本機檔案寫入或無效參數錯誤。
  • POST 更新主體和標頭,並傳回與字串相同的主體。不要因為回應為空就自動重複POST:伺服器可能已經執行了該操作。範例中的已接受/狀態檢查是與您的服務達成的協議,而不是HTTP-成功的內建標誌。

獨立的 C# 腳本

每個範例都可以儲存為單獨的檔案.csx並在IDE中運行。 UO物件和等待函數提供當前遊戲會話的主機。將演示 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。檢查服務的約定回應-直接腳本

參數與執行流程:

  • 該服務接受文字“路線已停止”,並根據協議以“接受”進行回應。 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 轉義字典字串。檢查JSON後讀取狀態值;將演示地址替換為您的地址。
return  RunScenario();
 object? RunScenario()
{
    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  new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
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;
    }

     public object? RunScenario()
    {
        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;
    }
}

命令實作

C# 區分大小寫。請使用正確的 UO 名稱。數值旗標應與 0 比較;只有回傳型別為 bool 時才使用 bool。

UO.HTTP_Post(url, postData) — UO.HTTP_Post(Any,Any)

參數: url (Any), postData (Any)

結果: dynamic / Any.

呼叫時:

內部實作程式碼,不能作為獨立腳本執行。

case "http_post":

                {

                    string[] response = bridge.HttpRequest("POST", Text(0), Text(1));

                    httpBody = response.Length > 0 ? response[0] : string.Empty;

                    httpHeader = response.Length > 1 ? response[1] : string.Empty;

                    return new InjectionValue(httpBody);

                }

UO.Messenger

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

C# 簽章

dynamic UO.Messenger(object? provider);

建立用於文字通知和接收 Telegram、Discord 或 Viber 訊息的物件。例如,腳本可以發出資源收集結束的訊號或檢查來自預先指定使用者的停止請求。創建物件尚未連接機器人,也不會發送任何內容。

參數

  • provider - string:「電報」、「不和諧」或「viber」;情況並不重要。其他值會導致錯誤。

傳回值

對象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:停止本地接收,清除token和遊標;可以再次連接該物件。 Dispose() → null:完全關閉物件。
  • SendMessage(text, recipient) → string:ID收到訊息。參數 - 文字和字串聊天 ID Telegram、頻道 ID Discord 或 ID Viber 訂閱者。長度限制:分別為4096/2000/7000;還有 Viber JSON ≤30000 位元組。禁止使用空白文字。 Discord 不會提及每個人/角色。
  • WatchChannel(channelId) → null:Discord,记住当前的最后一条消息并只读取后续消息。 WatchChannel(channelId, afterMessageId) → null:在给定字符串ID之后开始; “0”包含历史。每個物件最多 32 個通道。
  • Receive(timeoutSeconds) → Array;Receive():0超時。範圍0..20秒;空數組意味著沒有可用的簡訊。 Telegram 使用 long 輪詢,Discord 輪詢選定的頻道,Viber 讀取 webhook 隊列。網路請求最多可能需要 30 秒。
  • 每個MessengerMessage:Id()、SenderId()、SenderName()、ChatId()、Text() → string。來自某個頻道的 Telegram 貼文可能沒有 SenderId。來自機器人的附件、非文字事件和 Discord 訊息將不會被傳回。
  • RetryAfter() → int:限制服務後等待多少秒。在此期限到期之前,不會執行新的HTTP請求。失敗後不會自動重複發送:伺服器可能已經收到訊息。
  • StartReceiver(localPort, publicHttpsUrl) → int:僅限 Viber;port 1..65535,返回繁忙的本地端口。公共HTTPS地址必須以/viber/結尾,並提前將POST轉發到127.0.0.1:port/viber/,並附帶原始正文和簽名標頭。此方法向 Viber 註冊一個 webhook。
  • 您需要機器人令牌,而不是個人帳戶密碼。具有現有 Webhook 的 Telegram 將被拒絕而不將其刪除。 Discord 需要頻道讀取/傳送權限和 MESSAGE_CONTENT 才能存取文字; Viber 傳送給訂閱使用者。
  • Receive 僅在解析整個堆疊後才保存遊標。 Telegram/Discord 每個請求最多回傳 100 個條目;再次呼叫 Receive 來接收後續資料包。沒有第二個參數的 Discord WatchChannel 會跳過舊故事。
  • Viber 檢查來源內文的 HMAC-SHA256。佇列 - 儲存100訊息,重複的ID用於最後一次2048交付;溢出給出HTTP503供服務重試。您需要一個具有 Content-Length 的 HTTPS 代理;本地輸入的分塊請求被拒絕。
  • 此令牌不會記錄在 Connect 設定檔、錯誤文字或參數歷史記錄中。使用 ConnectFromFile 以避免將其儲存在偵錯器可見的腳本變數中。不要發布令牌文件。
  • 在過程中建立一個物件。同時不超過32;使用/處置可以更早釋放它。當腳本完成、失敗或停止時,其所有信使物件都將關閉。關閉 Viber 接收器不會從服務中刪除 Webhook。
  • 這是一個文字介面:它不會將接收到的文字作為程式碼執行,也不連接遊戲帳戶。信任寄件者的條件由腳本本身設定。

獨立的 C# 腳本

每個範例都可以儲存為單獨的檔案.csx並在IDE中運行。 UO物件和等待函數提供當前遊戲會話的主機。將演示 serial 名稱、座標和地址替換為您自己的。

簡單範例

將這段程式碼存為獨立的 .csx 檔案執行。參數直接出現在呼叫中;請將範例名稱、serial 和網址替換成自己的值。

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

1。 Telegram:工作完成後的通知 - 直接腳本

參數與執行流程:

  • 將 telegram-token.txt 放在腳本旁邊,將 12345678 替換為您的聊天記錄 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  RunScenario();
 object? RunScenario()
{
    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 讀取本機埠/publicUrl。令牌儲存在單獨的本機檔案中;此範例不執行實際調度。檢查受信任的SenderId,而不是任意傳入的文字。
return  new ScriptScenario(UO, WaitAsync, Args, Cancellation, Checkpoint).RunScenario();
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;
    }

     public object? RunScenario()
    {
        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;
}

命令實作

C# 區分大小寫。請使用正確的 UO 名稱。數值旗標應與 0 比較;只有回傳型別為 bool 時才使用 bool。

UO.Messenger(provider) — UO.Messenger(String)

參數: provider (String)

結果: dynamic / Object.

呼叫時:

內部實作程式碼,不能作為獨立腳本執行。

private InjectionObject CreateMessenger(string provider)
        {
            var owner=NativeScriptResourceScope.Current??throw new StatementFailedException("Create messenger objects inside an active C# script execution.");owner.Checkpoint();
            var client=MessengerFactory!=null?MessengerFactory(provider,()=>owner.Cancellation,owner.Checkpoint):new Messaging.MessengerClient(provider,()=>owner.Cancellation,owner.Checkpoint);
            var resource=new MessengerObject(client,owner.Forget,file=>Path.GetFullPath(Path.Combine(paths.ScriptPath??string.Empty,file)));owner.Track(resource);return resource;
        }

Clone this wiki locally