Skip to content

ES UO Topic http

Codex edited this page Oct 12, 2026 · 4 revisions

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

HTTP

Inicio · C# · IDE · UO API · A–Z · Ejemplos · Idiomas

HTTP-consultas y lectura de la respuesta. El código de estado, el encabezado y el cuerpo de la respuesta son datos separados.

Secciones

Tema Comandos y explicaciones
HTTP_Get UO.HTTP_Get
HTTP_Post UO.HTTP_Post
HTTP_Header UO.HTTP_Header
HTTP_Body UO.HTTP_Body
Mensajes externos UO.Messenger - Telegram, Discord y Viber

Todos los comandos del tema

HTTP Solicitudes

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

Ejemplos sobre el tema.

Cada tarjeta de comando tiene varios escenarios independientes: código directo, funciones y clases. A continuación se muestran escenarios breves seleccionados; restricciones y análisis completos están en las cartas.

UO.HTTP_Get

Parámetros, resultado y todos los escenarios

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

Parámetros, resultado y todos los escenarios

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();

Referencia completa de comandos


UO.HTTP_Body

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

Firmas de C#

dynamic UO.HTTP_Body();

Lee el texto de la última respuesta HTTP de este script. Por ejemplo, después de HTTP_Get puedes analizar JSON con la configuración o comparar la respuesta de tu servicio con la cadena esperada. La lectura en sí no va a la red.

Parámetros

No hay parámetros.

Valor devuelto

string — texto guardado. Antes de la primera solicitud en este tiempo de ejecución, después de GET en la secuencia y después del error de red: una línea vacía. Una respuesta normal también tiene un cuerpo vacío, por ejemplo HTTP 204. No compare el resultado con true/false como indicación de entrega.

Comportamiento

  • La última respuesta se almacena sólo en el tiempo de ejecución actual del script. El siguiente GET/POST de este tiempo de ejecución lo reemplaza; otros scripts que se ejecutan simultáneamente no lo cambian. La respuesta no se guarda en el perfil. Si lo necesita después de la siguiente solicitud, copie el cuerpo y los encabezados en variables con anticipación.
  • GET/POST espere una respuesta en el hilo del script en ejecución. El tiempo total para solicitar y leer el cuerpo es 20 segundos. Detener el guión cancela la espera; HTTP_Body/HTTP_Header no esperes nada. Todo el cuerpo se carga en la memoria incluso cuando se transfiere FileStream; Esta no es una descarga en streaming de archivos grandes.
  • El texto se decodifica según el juego de caracteres de la respuesta, en ausencia/codificación desconocida: UTF-8. También se leen las respuestas HTTP 4xx/5xx. Cuando hay un error de red o un tiempo de espera, el cliente escribe un error, el cuerpo y los encabezados quedan vacíos; Try/Catch no reemplaza la comprobación de la respuesta esperada. La cancelación de guion se extiende más allá. Try/Catch puede detectar un error de escritura en un archivo local o de un argumento no válido.
  • HTTP_Body solo lee el último búfer: no repite la solicitud, no borra la respuesta y no devuelve datos de otro script. Después del binario GET, use MemoryStream.ToArray() o un archivo almacenado, no este búfer de texto.

Scripts independientes de C#

Cada ejemplo se puede guardar como un archivo independiente .csx y ejecutar en IDE. Las funciones de objeto UO y de espera proporcionan el anfitrión de la sesión de juego actual. Reemplace los nombres, coordenadas y direcciones de la demostración serial por los suyos propios.

Ejemplo sencillo

Ejecuta este código en un archivo .csx independiente. Los argumentos aparecen en la llamada; sustituye los nombres, seriales y direcciones de ejemplo por los tuyos.

El resultado de una sola llamada se muestra en el diario. Un número no se convierte en bool; para un array se muestra su cantidad de elementos.

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

1. Permitir acción solo con el texto esperado: guión directo

Parámetros y flujo de ejecución:

  • El servicio debe volver a permitir. Otra respuesta, incluida una vacía, da false. El ejemplo simplemente calcula la resolución; no desencadena movimiento ni combate.
  • Las direcciones de ejemplo.com son ilustrativas y no proporcionan dicho servicio. Reemplácelos por los suyos propios; ejecutar el ejemplo genera una consulta HTTP real. El ejemplo no realiza acciones del juego.
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. Recopile una descripción de dos respuestas: función de script

Parámetros y flujo de ejecución:

  • Primero, se almacena el nombre de la ruta y luego se solicita una descripción. Sin routeName, el segundo GET reemplazaría la primera respuesta.
  • Las direcciones de ejemplo.com son ilustrativas y no proporcionan dicho servicio. Reemplácelos por los suyos propios; ejecutar el ejemplo genera una consulta HTTP real. El ejemplo no realiza acciones del juego.
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. Separar flujo binario del búfer de texto - clase de script

Parámetros y flujo de ejecución:

  • Después de GET con System.IO.MemoryStream, los bytes están en la secuencia y HTTP_Body está vacío. Esta regla también se aplica a una respuesta binaria correcta; El texto vacío no significa que no haya bytes.
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;
    }
}

Implementación del comando

C# distingue mayúsculas y minúsculas. Use el nombre UO exacto. Compare indicadores numéricos con 0; use bool solo si la firma devuelve bool.

UO.HTTP_Body() — UO.HTTP_Body()

Parámetros: Sin parámetros.

Resultado: dynamic / Any.

Durante la llamada:

Código interno de implementación; no es un script independiente.

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

UO.HTTP_Get

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

Firmas de C#

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

Carga datos en HTTP/HTTPS. Adecuado para leer configuraciones de su servicio o recibir un archivo; no gestiona la conexión del juego ni ejecuta el código descargado.

Parámetros

  • url - Requerido string: dirección completa http:// o https://. Reemplace ejemplo.com con la dirección de su servicio. El juego y el servidor del juego no son necesarios para esta solicitud; Se utiliza la conexión de red normal del proceso y no el perfil de proxy del juego.
  • lStream es un estándar opcional .NET System.IO.Stream, grabable: por ejemplo, nuevo System.IO.MemoryStream() o System.IO.File.Create(ruta). Sin él o con 0/null el texto dice HTTP_Body(). El hilo recibe los bytes originales. Para una secuencia buscable, el contenido anterior se restablece a cero y la posición antes y después de la escritura se convierte en 0; El hilo no buscable recibe una escritura en la posición actual. Crear FileStream a través de File.Create anula el archivo inmediatamente; el directorio principal debe existir. Un argumento inapropiado o una secuencia de solo lectura se rechaza antes de la solicitud.

Valor devuelto

void: sin valor de retorno. Llame en una línea separada; el resultado no se puede utilizar como bool, ID o número de bytes. HTTP_Body() lee el texto después de una solicitud normal, los datos binarios se leen del flujo transmitido.

Comportamiento

  • La última respuesta se almacena sólo en el tiempo de ejecución actual del script. El siguiente GET/POST de este tiempo de ejecución lo reemplaza; otros scripts que se ejecutan simultáneamente no lo cambian. La respuesta no se guarda en el perfil. Si lo necesita después de la siguiente solicitud, copie el cuerpo y los encabezados en variables con anticipación.
  • GET/POST espere una respuesta en el hilo del script en ejecución. El tiempo total para solicitar y leer el cuerpo es 20 segundos. Detener el guión cancela la espera; HTTP_Body/HTTP_Header no esperes nada. Todo el cuerpo se carga en la memoria incluso cuando se transfiere FileStream; Esta no es una descarga en streaming de archivos grandes.
  • El texto se decodifica según el juego de caracteres de la respuesta, en ausencia/codificación desconocida: UTF-8. También se leen las respuestas HTTP 4xx/5xx. Cuando hay un error de red o un tiempo de espera, el cliente escribe un error, el cuerpo y los encabezados quedan vacíos; Try/Catch no reemplaza la comprobación de la respuesta esperada. La cancelación de guion se extiende más allá. Try/Catch puede detectar un error de escritura en un archivo local o de un argumento no válido.
  • GET sin hilo actualiza texto y encabezados. GET con flujo escribe bytes, borra HTTP_Body y guarda encabezados. Incluso una respuesta vacía/error de red reemplaza el contenido de la transmisión con datos vacíos: para guardar el archivo antiguo, primero descárguelo a MemoryStream y verifique los datos.

Scripts independientes de C#

Cada ejemplo se puede guardar como un archivo independiente .csx y ejecutar en IDE. Las funciones de objeto UO y de espera proporcionan el anfitrión de la sesión de juego actual. Reemplace los nombres, coordenadas y direcciones de la demostración serial por los suyos propios.

Ejemplo sencillo

Ejecuta este código en un archivo .csx independiente. Los argumentos aparecen en la llamada; sustituye los nombres, seriales y direcciones de ejemplo por los tuyos.

El comando es una instrucción independiente. El mensaje anterior indica el inicio de la llamada y no confirma una acción del servidor.

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

1. Leer JSON-configuración con verificación de rango - script directo

Parámetros y flujo de ejecución:

  • ejemplo.com - dirección de demostración; reemplázalo por el tuyo. System.Text.Json lee el cuerpo de la respuesta y solo acepta el número entero minMana de 0 a 100. Un JSON vacío/no válido proporciona el valor predeterminado 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. Verifique los bytes binarios antes de guardar el archivo: función de secuencia de comandos

Parámetros y flujo de ejecución:

  • Se transmite el sistema estándar.IO.MemoryStream. Recibe los bytes originales de la respuesta; HTTP_Body queda vacío. El download.bin existente se reemplaza solo después de recibir datos que no estén vacíos. Verificar la longitud no prueba que el contenido sea correcto.
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. Descargue la respuesta binaria directamente en FileStream - clase de script

Parámetros y flujo de ejecución:

  • System.IO.File.Create crea o anula inmediatamente un archivo; GET escribe los bytes originales. Si la respuesta está vacía, el archivo permanecerá vacío. Para guardar la versión anterior, primero use MemoryStream como en el script anterior. El uso cierra la transmisión.
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;
    }
}

Implementación del comando

C# distingue mayúsculas y minúsculas. Use el nombre UO exacto. Compare indicadores numéricos con 0; use bool solo si la firma devuelve bool.

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

Parámetros: url (Any)

Resultado: void / Unit.

Durante la llamada:

Código interno de implementación; no es un script independiente.

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)

Parámetros: url (Any), lStream (Any)

Resultado: void / Unit.

Durante la llamada:

Código interno de implementación; no es un script independiente.

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);

Código interno de implementación; no es un script independiente.

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 · 繁體中文 · 日本語 · 한국어

Firmas de C#

dynamic UO.HTTP_Header();

Lee los encabezados de la última respuesta HTTP de este script: por ejemplo, Content-Type, para conocer el formato de datos declarado. Este no es el cuerpo de la respuesta, los encabezados de la solicitud ni el código numérico HTTP.

Parámetros

No hay parámetros.

Valor devuelto

string — líneas del formulario Nombre: valor, separadas por CRLF. Antes de la primera solicitud y después del error de red: una línea vacía. Las líneas HTTP/1.1 200 OK no están aquí; El código de estado no está representado por un comando separado. El orden y caso de los nombres no está garantizado.

Comportamiento

  • La última respuesta se almacena sólo en el tiempo de ejecución actual del script. El siguiente GET/POST de este tiempo de ejecución lo reemplaza; otros scripts que se ejecutan simultáneamente no lo cambian. La respuesta no se guarda en el perfil. Si lo necesita después de la siguiente solicitud, copie el cuerpo y los encabezados en variables con anticipación.
  • GET/POST espere una respuesta en el hilo del script en ejecución. El tiempo total para solicitar y leer el cuerpo es 20 segundos. Detener el guión cancela la espera; HTTP_Body/HTTP_Header no esperes nada. Todo el cuerpo se carga en la memoria incluso cuando se transfiere FileStream; Esta no es una descarga en streaming de archivos grandes.
  • El texto se decodifica según el juego de caracteres de la respuesta, en ausencia/codificación desconocida: UTF-8. También se leen las respuestas HTTP 4xx/5xx. Cuando hay un error de red o un tiempo de espera, el cliente escribe un error, el cuerpo y los encabezados quedan vacíos; Try/Catch no reemplaza la comprobación de la respuesta esperada. La cancelación de guion se extiende más allá. Try/Catch puede detectar un error de escritura en un archivo local o de un argumento no válido.
  • HTTP_Header combina los encabezados de la respuesta y su contenido. Después del binario GET también están disponibles. El nombre debe comprobarse sin distinguir entre mayúsculas y minúsculas. Content-Type es una declaración del servidor, no una verificación de contenido; No ejecute el texto descargado como código.

Scripts independientes de C#

Cada ejemplo se puede guardar como un archivo independiente .csx y ejecutar en IDE. Las funciones de objeto UO y de espera proporcionan el anfitrión de la sesión de juego actual. Reemplace los nombres, coordenadas y direcciones de la demostración serial por los suyos propios.

Ejemplo sencillo

Ejecuta este código en un archivo .csx independiente. Los argumentos aparecen en la llamada; sustituye los nombres, seriales y direcciones de ejemplo por los tuyos.

El resultado de una sola llamada se muestra en el diario. Un número no se convierte en bool; para un array se muestra su cantidad de elementos.

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

1. Leer el encabezado de respuesta sin distinguir entre mayúsculas y minúsculas: script directo

Parámetros y flujo de ejecución:

  • Los títulos se analizan línea por línea. El nombre del tipo de contenido se compara sin distinguir entre mayúsculas y minúsculas; si no hay ninguna cadena, se devuelve una cadena vacía.
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. Verificación declarada JSON Tipo de contenido - función de script

Parámetros y flujo de ejecución:

  • Se comprueba el texto del encabezado guardado localmente. El tipo de contenido en sí no garantiza la exactitud de JSON; verifique el contenido por separado 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. Guardar encabezados de respuesta binaria: clase de secuencia de comandos

Parámetros y flujo de ejecución:

  • GET reenvía los bytes de origen a System.IO.MemoryStream. Los encabezados de las últimas respuestas todavía dicen HTTP_Header; El texto HTTP_Body para este formulario está vacío. Sólo los encabezados se guardan en el archivo.
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;
    }
}

Implementación del comando

C# distingue mayúsculas y minúsculas. Use el nombre UO exacto. Compare indicadores numéricos con 0; use bool solo si la firma devuelve bool.

UO.HTTP_Header() — UO.HTTP_Header()

Parámetros: Sin parámetros.

Resultado: dynamic / Any.

Durante la llamada:

Código interno de implementación; no es un script independiente.

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

UO.HTTP_Post

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

Firmas de C#

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

Envía un texto a su servicio HTTP utilizando el método POST y devuelve el texto de respuesta. Por ejemplo, un script puede informar una parada de ruta. Este no es un comando de Telegram/Discord ya preparado: su protocolo, autorización y formato de solicitud requieren soporte por separado.

Parámetros

  • url - Requerido string: dirección completa http:// o https://. Reemplace ejemplo.com con la dirección de su servicio. El juego y el servidor del juego no son necesarios para esta solicitud; Se utiliza la conexión de red normal del proceso y no el perfil de proxy del juego.
  • postData — Obligatorio string con cuerpo de solicitud. Enviado por UTF-8 con tipo de contenido: texto/sin formato; conjunto de caracteres=utf-8. No hay codificación de formulario automática ni cambio a aplicación/json. System.Text.Json.JsonSerializer.Serialize solo genera texto: el servidor de ejemplo debería aceptar JSON exactamente como texto/sin formato. No puede configurar encabezados personalizados usando estos comandos.

Valor devuelto

string — texto de respuesta; también es accesible a través de HTTP_Body(). Esto no es bool ni el código HTTP. Una cadena vacía no indica un error, pero una cadena no vacía no indica éxito de la operación en el servidor.

Comportamiento

  • La última respuesta se almacena sólo en el tiempo de ejecución actual del script. El siguiente GET/POST de este tiempo de ejecución lo reemplaza; otros scripts que se ejecutan simultáneamente no lo cambian. La respuesta no se guarda en el perfil. Si lo necesita después de la siguiente solicitud, copie el cuerpo y los encabezados en variables con anticipación.
  • GET/POST espere una respuesta en el hilo del script en ejecución. El tiempo total para solicitar y leer el cuerpo es 20 segundos. Detener el guión cancela la espera; HTTP_Body/HTTP_Header no esperes nada. Todo el cuerpo se carga en la memoria incluso cuando se transfiere FileStream; Esta no es una descarga en streaming de archivos grandes.
  • El texto se decodifica según el juego de caracteres de la respuesta, en ausencia/codificación desconocida: UTF-8. También se leen las respuestas HTTP 4xx/5xx. Cuando hay un error de red o un tiempo de espera, el cliente escribe un error, el cuerpo y los encabezados quedan vacíos; Try/Catch no reemplaza la comprobación de la respuesta esperada. La cancelación de guion se extiende más allá. Try/Catch puede detectar un error de escritura en un archivo local o de un argumento no válido.
  • POST actualiza el cuerpo y los encabezados y devuelve el mismo cuerpo como una cadena. No repita POST automáticamente solo porque la respuesta esté vacía: es posible que el servidor ya haya realizado la acción. La verificación de estado/aceptado en los ejemplos es un acuerdo con su servicio, no una señal incorporada de éxito HTTP.

Scripts independientes de C#

Cada ejemplo se puede guardar como un archivo independiente .csx y ejecutar en IDE. Las funciones de objeto UO y de espera proporcionan el anfitrión de la sesión de juego actual. Reemplace los nombres, coordenadas y direcciones de la demostración serial por los suyos propios.

Ejemplo sencillo

Ejecuta este código en un archivo .csx independiente. Los argumentos aparecen en la llamada; sustituye los nombres, seriales y direcciones de ejemplo por los tuyos.

El resultado de una sola llamada se muestra en el diario. Un número no se convierte en bool; para un array se muestra su cantidad de elementos.

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

1. Consulta la respuesta acordada del servicio - guión directo

Parámetros y flujo de ejecución:

  • El servicio acepta el texto Ruta detenida y, de acuerdo, responde con aceptado. Main regresa true solo con este texto; Esta es una verificación del protocolo de su servicio, no una verificación del código HTTP.
  • Las direcciones de ejemplo.com son ilustrativas y no proporcionan dicho servicio. Reemplácelos por los suyos propios; ejecutar el ejemplo genera una consulta HTTP real. El ejemplo no realiza acciones del juego.
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. Enviar serializado JSON y analizar la respuesta JSON - función de script

Parámetros y flujo de ejecución:

  • System.Text.Json.JsonSerializer escapa de las cadenas del diccionario. El valor de estado se lee después de verificar JSON; Reemplace la dirección de demostración por la suya.
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. Guardar respuesta hasta la próxima solicitud - clase de script

Parámetros y flujo de ejecución:

  • firstReply y firstHeaders almacenan la respuesta POST. El GET posterior reemplaza los buffers internos, pero las variables locales aún contienen la primera respuesta.
  • Las direcciones de ejemplo.com son ilustrativas y no proporcionan dicho servicio. Reemplácelos por los suyos propios; ejecutar el ejemplo genera una consulta HTTP real. El ejemplo no realiza acciones del juego.
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;
    }
}

Implementación del comando

C# distingue mayúsculas y minúsculas. Use el nombre UO exacto. Compare indicadores numéricos con 0; use bool solo si la firma devuelve bool.

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

Parámetros: url (Any), postData (Any)

Resultado: dynamic / Any.

Durante la llamada:

Código interno de implementación; no es un script independiente.

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 · 繁體中文 · 日本語 · 한국어

Firmas de C#

dynamic UO.Messenger(object? provider);

Crea un objeto para notificaciones de texto y recibir mensajes de Telegram, Discord o Viber. Por ejemplo, el script podría señalar el final de la recopilación de recursos o comprobar si hay una solicitud de detención de un usuario previamente especificado. La creación de un objeto aún no conecta el bot y no envía nada.

Parámetros

  • provider - string: "telegrama", "discordia" o "viber"; El caso no es importante. Otros valores provocan un error.

Valor devuelto

Objeto Messenger. Esto no es bool ni ID. ID los mensajes, remitentes y chats en este objeto son siempre string: compárelos con cadenas, no los convierta mediante Convert.ToInt32/Convert.ToDouble.

Comportamiento

  • Provider() → string; Connected() → 1/0 (true/false): Proveedor y resultado de la última verificación de autorización. Connected no garantiza la disponibilidad de Internet en este segundo.
  • Connect(token) → null: verifica el token del bot; ConnectFromFile(path) → null: Lee el token UTF-8 del archivo hasta 1024 bytes. La ruta relativa se calcula a partir de la carpeta de script actual. La reconexión requiere Disconnect. Los errores pueden detectarse mediante Try/Catch.
  • Disconnect() → null: detiene la recepción local, borra el token y los cursores; el objeto se puede volver a conectar. Dispose() → null: cierra el objeto por completo.
  • SendMessage(text, recipient) → string: ID mensaje recibido. Parámetros: chat de texto y cadenas ID Telegram, canal ID Discord o ID Suscriptor de Viber. Límites de longitud: 4096/2000/7000 respectivamente; también Viber JSON ≤30000 bytes. Está prohibido el texto en blanco. Discord no crea menciones de todos/roles.
  • WatchChannel(channelId) → null: Discord, recuerda el último mensaje actual y lee solo los siguientes. WatchChannel(channelId, afterMessageId) → null: comienza después de la cadena dada ID; "0" incluye el historial. Hasta 32 canales por objeto.
  • Receive(timeoutSeconds) → Array; Receive(): 0 tiempo de espera. Rango 0..20 segundos; una matriz vacía significa que no hay mensajes de texto disponibles. Telegram usa sondeo long, Discord sondea los canales seleccionados, Viber lee la cola de webhook. La solicitud de red puede tardar hasta 30 segundos.
  • Cada MessengerMessage: Id(), SenderId(), SenderName(), ChatId(), Text() → string. Es posible que una publicación de Telegram de un canal no tenga SenderId. No se devolverán archivos adjuntos, eventos que no sean de texto y mensajes de Discord de bots.
  • RetryAfter() → int: cuántos segundos esperar después de limitar el servicio. Antes de que expire este período, las nuevas solicitudes HTTP no se ejecutan. El envío después de un error no se repite automáticamente: es posible que el servidor ya haya recibido el mensaje.
  • StartReceiver(localPort, publicHttpsUrl) → int: solo Viber; puerto 1..65535, devuelve el puerto local ocupado. La dirección pública HTTPS debe terminar con /viber/ y reenviar POST a 127.0.0.1:port/viber/ con el cuerpo original y el encabezado de firma por adelantado. El método registra un webhook con Viber.
  • Necesita un token de bot, no una contraseña de cuenta personal. Telegram con un webhook existente se rechaza sin eliminarlo. Discord requiere permisos de lectura/envío del canal y MESSAGE_CONTENT para texto accesible; Viber envía a usuarios suscritos.
  • Recibir guarda el cursor solo después de analizar toda la pila. Telegram/Discord devuelve hasta 100 entradas por solicitud; llame a Recibir nuevamente para paquetes posteriores. Discord sin el segundo argumento WatchChannel se salta la vieja historia.
  • Viber verifica el HMAC-SHA256 del cuerpo fuente. Cola: los mensajes 100 repetidos ID se almacenan para las últimas entregas 2048; el desbordamiento proporciona HTTP 503 para reintentar por servicio. Necesita un proxy HTTPS con longitud de contenido; Las solicitudes fragmentadas en la entrada local se rechazan.
  • El token no se registra en el perfil de Connect, el texto de error ni el historial de argumentos. Utilice ConnectFromFile para evitar almacenarlo en variables de script visibles para el depurador. No publique archivos token.
  • Crea un objeto dentro de un procedimiento. No más de 32 al mismo tiempo; Usar/Desechar lo libera antes. Cuando un script se completa, falla o se detiene, todos sus objetos de mensajería se cierran. Cerrar el receptor de Viber no elimina el webhook del servicio.
  • Esta es una interfaz de texto: no ejecuta el texto recibido como código y no conecta cuentas de juegos. Las condiciones para confiar en el remitente las establece el propio script.

Scripts independientes de C#

Cada ejemplo se puede guardar como un archivo independiente .csx y ejecutar en IDE. Las funciones de objeto UO y de espera proporcionan el anfitrión de la sesión de juego actual. Reemplace los nombres, coordenadas y direcciones de la demostración serial por los suyos propios.

Ejemplo sencillo

Ejecuta este código en un archivo .csx independiente. Los argumentos aparecen en la llamada; sustituye los nombres, seriales y direcciones de ejemplo por los tuyos.

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

1. Telegram: notificación después de completar el trabajo - guión directo

Parámetros y flujo de ejecución:

  • Coloque telegram-token.txt al lado del script, reemplace 12345678 con su chat ID. El ejemplo envía una notificación y devuelve la cadena ID; recibir una respuesta del servidor no confirma la lectura humana.
  • Necesitas tu propia configuración de bot. Los ejemplos se prueban con respuestas de pruebas locales; no fueron enviados a usuarios reales.
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: Detener solicitud del usuario seleccionado - Función de secuencia de comandos

Parámetros y flujo de ejecución:

  • Ingrese a su canal y ID remitente permitido. true significa que este cheque recibió el texto stop de él; el ejemplo en sí no detiene el movimiento. Este resultado se puede utilizar en su propia condición de ciclo de trabajo.
  • Necesitas tu propia configuración de bot. Los ejemplos se prueban con respuestas de pruebas locales; no fueron enviados a usuarios reales.
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. Cargar la configuración del receptor desde el archivo JSON - clase de script

Parámetros y flujo de ejecución:

  • System.Text.Json lee el puerto local/publicUrl. El token se almacena en un archivo local independiente; Los despachos reales no se realizan en este ejemplo. Se marca SenderId de confianza, no texto entrante arbitrario.
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;
}

Implementación del comando

C# distingue mayúsculas y minúsculas. Use el nombre UO exacto. Compare indicadores numéricos con 0; use bool solo si la firma devuelve bool.

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

Parámetros: provider (String)

Resultado: dynamic / Object.

Durante la llamada:

Código interno de implementación; no es un script independiente.

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