Skip to content

FR UO Topic http

Codex edited this page Oct 12, 2026 · 4 revisions

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

HTTP

Accueil · C# · IDE · UO API · A–Z · Exemples · Langues

HTTP-requêtes et lecture de la réponse. Le code d'état, l'en-tête et le corps de la réponse sont des données distinctes.

Sections

Sujet Commandes et explications
HTTP_Get UO.HTTP_Get
HTTP_Post UO.HTTP_Post
HTTP_Header UO.HTTP_Header
HTTP_Body UO.HTTP_Body
Messages externes UO.Messenger - Télégramme, Discord et Viber

Toutes les commandes du thème

HTTP Requêtes

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

Exemples sur le sujet

Chaque carte de commande possède plusieurs scénarios indépendants : code direct, fonctions et classes. Vous trouverez ci-dessous une sélection de courts scénarios ; des restrictions et une analyse complète sont à prévoir.

UO.HTTP_Get

Paramètres, résultat et tous les scénarios

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

Paramètres, résultat et tous les scénarios

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

Référence complète des commandes


UO.HTTP_Body

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

Signatures C#

dynamic UO.HTTP_Body();

Lit le texte de la dernière réponse HTTP de ce script. Par exemple, après HTTP_Get, vous pouvez analyser JSON avec les paramètres ou comparer la réponse de votre service avec la chaîne attendue. La lecture elle-même ne va pas au réseau.

Paramètres

Il n'y a pas de paramètres.

Valeur de retour

string — texte enregistré. Avant la première requête dans ce runtime, après GET dans le flux et après l'erreur réseau - une ligne vide. Une réponse normale a également un corps vide, par exemple HTTP 204. Ne comparez pas le résultat avec true/false comme indication de livraison.

Comportement

  • La dernière réponse est stockée uniquement dans le runtime actuel du script. Le prochain GET/POST de ce runtime le remplace ; les autres scripts exécutés simultanément ne le modifient pas. La réponse n'est pas enregistrée dans le profil. Si vous en avez besoin après la prochaine requête, copiez au préalable le corps et les en-têtes dans les variables.
  • GET/POST attendez une réponse dans le fil de script en cours d'exécution. Le temps total pour demander et lire le corps est de 20 secondes. L'arrêt du script annule l'attente ; HTTP_Body/HTTP_Header n'attendez rien. Le corps entier est chargé en mémoire même lorsque FileStream est transféré ; Il ne s’agit pas d’un téléchargement en continu de fichiers volumineux.
  • Le texte est décodé selon le jeu de caractères de la réponse, en l'absence/encodage inconnu - UTF-8. Les réponses HTTP 4xx/5xx sont également lues. Lorsqu'il y a une erreur réseau ou un délai d'attente, le client écrit une erreur, le corps et les en-têtes deviennent vides ; Try/Catch ne remplace pas la vérification de la réponse attendue. L'annulation du script s'étend plus loin. Une erreur d'écriture de fichier local ou d'argument non valide peut être détectée par Try/Catch.
  • HTTP_Body ne lit que le dernier tampon : il ne répète pas la requête, n'efface pas la réponse et ne renvoie pas les données d'un autre script. Après le binaire GET, utilisez MemoryStream.ToArray() ou un fichier stocké, pas ce tampon de texte.

Scripts C# autonomes

Chaque exemple peut être enregistré dans un fichier séparé .csx et exécuté dans IDE. Les fonctions d'objet UO et d'attente fournissent l'hôte de la session de jeu en cours. Remplacez les noms, coordonnées et adresses de la démo serial par les vôtres.

Exemple simple

Exécutez ce code dans un fichier .csx séparé. Les arguments sont visibles dans l’appel ; remplacez les noms, serials et adresses d’exemple par les vôtres.

Le résultat d’un seul appel est affiché dans le journal. Un nombre n’est pas converti en bool ; un tableau est affiché par son nombre d’éléments.

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

1. Autoriser l'action uniquement avec le texte attendu - script direct

Paramètres et déroulement de l’exécution :

  • Le service doit revenir permettre. Une autre réponse, y compris une réponse vide, donne false. L'exemple calcule simplement la résolution ; ne déclenche ni mouvement ni combat.
  • Les adresses example.com sont illustratives et ne fournissent pas un tel service. Remplacez-les par les vôtres ; l'exécution de l'exemple crée une véritable requête HTTP. L'exemple n'effectue pas d'actions de jeu.
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. Recueillir une description à partir de deux réponses - fonction de script

Paramètres et déroulement de l’exécution :

  • Tout d'abord, le nom de l'itinéraire est enregistré, puis une description est demandée. Sans routeName, le deuxième GET remplacerait la première réponse.
  • Les adresses example.com sont illustratives et ne fournissent pas un tel service. Remplacez-les par les vôtres ; l'exécution de l'exemple crée une véritable requête HTTP. L'exemple n'effectue pas d'actions de jeu.
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. Séparer le flux binaire du tampon de texte - classe de script

Paramètres et déroulement de l’exécution :

  • Après GET avec System.IO.MemoryStream les octets sont dans le flux et HTTP_Body est vide. Cette règle s'applique également à une réponse binaire correcte ; un texte vide ne signifie pas qu'il n'y a pas d'octets.
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;
    }
}

Implémentation de la commande

C# distingue les majuscules. Utilisez le nom UO exact. Comparez les indicateurs numériques à 0 ; utilisez bool seulement si la signature renvoie bool.

UO.HTTP_Body() — UO.HTTP_Body()

Paramètres: Aucun paramètre.

Résultat: dynamic / Any.

Pendant un appel:

Code interne de l’implémentation ; ce n’est pas un script autonome.

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

UO.HTTP_Get

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

Signatures C#

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

Charge les données sur HTTP/HTTPS. Convient pour lire les paramètres de votre service ou recevoir un fichier ; ne gère pas la connexion du jeu et n'exécute pas le code téléchargé.

Paramètres

  • url - Obligatoire string : adresse complète http:// ou https://. Remplacez exemple.com par l'adresse de votre service. Le jeu et le serveur de jeu ne sont pas nécessaires pour cette requête ; La connexion réseau normale du processus est utilisée, et non le profil proxy du jeu.
  • lStream est un standard facultatif .NET System.IO.Stream, inscriptible : par exemple new System.IO.MemoryStream() ou System.IO.File.Create(path). Sans cela ou avec 0/null le texte se lit HTTP_Body(). Le thread reçoit les octets d'origine. Pour un flux recherché, le contenu précédent est réinitialisé à zéro et la position avant et après l'écriture devient 0 ; Le thread non recherché reçoit une écriture à la position actuelle. La création de FileStream via File.Create annule immédiatement le fichier ; le répertoire parent doit exister. Un argument inapproprié ou un flux en lecture seule est rejeté avant la requête.

Valeur de retour

void - aucune valeur de retour. Appelez sur une ligne séparée ; le résultat ne peut pas être utilisé comme bool, ID ou nombre d'octets. Le texte après une requête normale est lu par HTTP_Body(), les données binaires sont lues à partir du flux transmis.

Comportement

  • La dernière réponse est stockée uniquement dans le runtime actuel du script. Le prochain GET/POST de ce runtime le remplace ; les autres scripts exécutés simultanément ne le modifient pas. La réponse n'est pas enregistrée dans le profil. Si vous en avez besoin après la prochaine requête, copiez au préalable le corps et les en-têtes dans les variables.
  • GET/POST attendez une réponse dans le fil de script en cours d'exécution. Le temps total pour demander et lire le corps est de 20 secondes. L'arrêt du script annule l'attente ; HTTP_Body/HTTP_Header n'attendez rien. Le corps entier est chargé en mémoire même lorsque FileStream est transféré ; Il ne s’agit pas d’un téléchargement en continu de fichiers volumineux.
  • Le texte est décodé selon le jeu de caractères de la réponse, en l'absence/encodage inconnu - UTF-8. Les réponses HTTP 4xx/5xx sont également lues. Lorsqu'il y a une erreur réseau ou un délai d'attente, le client écrit une erreur, le corps et les en-têtes deviennent vides ; Try/Catch ne remplace pas la vérification de la réponse attendue. L'annulation du script s'étend plus loin. Une erreur d'écriture de fichier local ou d'argument non valide peut être détectée par Try/Catch.
  • GET sans fil met à jour le texte et les titres. GET avec le flux écrit des octets, efface HTTP_Body et enregistre les en-têtes. Même une réponse vide/erreur réseau remplace le contenu du flux par des données vides : pour enregistrer l'ancien fichier, téléchargez-le d'abord sur MemoryStream et vérifiez les données.

Scripts C# autonomes

Chaque exemple peut être enregistré dans un fichier séparé .csx et exécuté dans IDE. Les fonctions d'objet UO et d'attente fournissent l'hôte de la session de jeu en cours. Remplacez les noms, coordonnées et adresses de la démo serial par les vôtres.

Exemple simple

Exécutez ce code dans un fichier .csx séparé. Les arguments sont visibles dans l’appel ; remplacez les noms, serials et adresses d’exemple par les vôtres.

La commande forme une instruction séparée. Le message précédent indique le début de l’appel et ne confirme aucune action du serveur.

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

1. Lire la configuration JSON avec vérification de plage - script direct

Paramètres et déroulement de l’exécution :

  • example.com - adresse de démonstration ; remplacez-le par le vôtre. System.Text.Json lit le corps de la réponse et n'accepte que l'entier minMana de 0 à 100. Un JSON vide/invalide donne la valeur par défaut 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. Vérifiez les octets binaires avant d'enregistrer le fichier - fonction de script

Paramètres et déroulement de l’exécution :

  • Le standard System.IO.MemoryStream est transmis. Il reçoit les octets originaux de la réponse ; HTTP_Body devient vide. Le download.bin existant n'est remplacé qu'après réception de données non vides. Vérifier la longueur ne prouve pas que le contenu est correct.
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. Téléchargez la réponse binaire directement dans FileStream - classe de script

Paramètres et déroulement de l’exécution :

  • System.IO.File.Create crée ou annule immédiatement un fichier ; GET écrit les octets d'origine. Si la réponse est vide, le fichier restera vide. Pour enregistrer la version précédente, utilisez d'abord MemoryStream comme dans le script précédent. using ferme le flux.
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;
    }
}

Implémentation de la commande

C# distingue les majuscules. Utilisez le nom UO exact. Comparez les indicateurs numériques à 0 ; utilisez bool seulement si la signature renvoie bool.

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

Paramètres: url (Any)

Résultat: void / Unit.

Pendant un appel:

Code interne de l’implémentation ; ce n’est pas un script autonome.

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)

Paramètres: url (Any), lStream (Any)

Résultat: void / Unit.

Pendant un appel:

Code interne de l’implémentation ; ce n’est pas un script autonome.

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

Code interne de l’implémentation ; ce n’est pas un script autonome.

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

Signatures C#

dynamic UO.HTTP_Header();

Lit les en-têtes de la dernière réponse HTTP de ce script : par exemple, Content-Type, pour connaître le format de données déclaré. Il ne s'agit pas du corps de la réponse, des en-têtes de requête ou du code numérique HTTP.

Paramètres

Il n'y a pas de paramètres.

Valeur de retour

string — chaînes de la forme Nom : valeur, séparées par CRLF. Avant la première requête et après l'erreur réseau - une ligne vide. Les lignes HTTP/1.1 200 OK ne sont pas ici ; Le code d'état n'est pas représenté par une commande distincte. L'ordre et la casse des noms ne sont pas garantis.

Comportement

  • La dernière réponse est stockée uniquement dans le runtime actuel du script. Le prochain GET/POST de ce runtime le remplace ; les autres scripts exécutés simultanément ne le modifient pas. La réponse n'est pas enregistrée dans le profil. Si vous en avez besoin après la prochaine requête, copiez au préalable le corps et les en-têtes dans les variables.
  • GET/POST attendez une réponse dans le fil de script en cours d'exécution. Le temps total pour demander et lire le corps est de 20 secondes. L'arrêt du script annule l'attente ; HTTP_Body/HTTP_Header n'attendez rien. Le corps entier est chargé en mémoire même lorsque FileStream est transféré ; Il ne s’agit pas d’un téléchargement en continu de fichiers volumineux.
  • Le texte est décodé selon le jeu de caractères de la réponse, en l'absence/encodage inconnu - UTF-8. Les réponses HTTP 4xx/5xx sont également lues. Lorsqu'il y a une erreur réseau ou un délai d'attente, le client écrit une erreur, le corps et les en-têtes deviennent vides ; Try/Catch ne remplace pas la vérification de la réponse attendue. L'annulation du script s'étend plus loin. Une erreur d'écriture de fichier local ou d'argument non valide peut être détectée par Try/Catch.
  • HTTP_Header combine les en-têtes de la réponse et son contenu. Après le binaire GET, ils sont également disponibles. Le nom doit être vérifié sans tenir compte de la casse. Content-Type est une instruction de serveur, pas une vérification de contenu ; n'exécutez pas le texte téléchargé sous forme de code.

Scripts C# autonomes

Chaque exemple peut être enregistré dans un fichier séparé .csx et exécuté dans IDE. Les fonctions d'objet UO et d'attente fournissent l'hôte de la session de jeu en cours. Remplacez les noms, coordonnées et adresses de la démo serial par les vôtres.

Exemple simple

Exécutez ce code dans un fichier .csx séparé. Les arguments sont visibles dans l’appel ; remplacez les noms, serials et adresses d’exemple par les vôtres.

Le résultat d’un seul appel est affiché dans le journal. Un nombre n’est pas converti en bool ; un tableau est affiché par son nombre d’éléments.

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

1. Lire l'en-tête de réponse sans respecter la casse - script direct

Paramètres et déroulement de l’exécution :

  • Les titres sont analysés ligne par ligne. Le nom Content-Type est comparé sans tenir compte de la casse ; s'il n'y a pas de chaîne, une chaîne vide est renvoyée.
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. Vérifiez déclaré JSON Content-Type - fonction de script

Paramètres et déroulement de l’exécution :

  • Le texte d'en-tête enregistré localement est vérifié. Content-Type lui-même ne garantit pas l'exactitude de JSON ; vérifiez le contenu séparément 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. Enregistrer les en-têtes de réponse binaire - Classe de script

Paramètres et déroulement de l’exécution :

  • GET transmet les octets sources à System.IO.MemoryStream. Les derniers en-têtes de réponse indiquent toujours HTTP_Header ; le texte HTTP_Body de ce formulaire est vide. Seuls les en-têtes sont enregistrés dans le fichier.
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;
    }
}

Implémentation de la commande

C# distingue les majuscules. Utilisez le nom UO exact. Comparez les indicateurs numériques à 0 ; utilisez bool seulement si la signature renvoie bool.

UO.HTTP_Header() — UO.HTTP_Header()

Paramètres: Aucun paramètre.

Résultat: dynamic / Any.

Pendant un appel:

Code interne de l’implémentation ; ce n’est pas un script autonome.

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

UO.HTTP_Post

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

Signatures C#

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

Envoie un texte à son service HTTP en utilisant la méthode POST et renvoie le texte de réponse. Par exemple, un script peut signaler un arrêt d'itinéraire. Il ne s'agit pas d'une commande Telegram/Discord toute faite : leur protocole, leur autorisation et leur format de demande nécessitent un support séparé.

Paramètres

  • url - Obligatoire string : adresse complète http:// ou https://. Remplacez exemple.com par l'adresse de votre service. Le jeu et le serveur de jeu ne sont pas nécessaires pour cette requête ; La connexion réseau normale du processus est utilisée, et non le profil proxy du jeu.
  • postData — Obligatoire string avec le corps de la demande. Envoyé par UTF-8 avec Content-Type : text/plain ; charset=utf-8. Il n'y a pas d'encodage de formulaire automatique ni de passage à application/json. System.Text.Json.JsonSerializer.Serialize génère uniquement du texte : l'exemple de serveur doit accepter JSON exactement comme text/plain. Vous ne pouvez pas configurer d'en-têtes personnalisés à l'aide de ces commandes.

Valeur de retour

string — texte de réponse ; il est également accessible via HTTP_Body(). Ce n'est pas bool ni le code HTTP. Une chaîne vide n'indique pas une erreur, mais une chaîne non vide n'indique pas la réussite de l'opération sur le serveur.

Comportement

  • La dernière réponse est stockée uniquement dans le runtime actuel du script. Le prochain GET/POST de ce runtime le remplace ; les autres scripts exécutés simultanément ne le modifient pas. La réponse n'est pas enregistrée dans le profil. Si vous en avez besoin après la prochaine requête, copiez au préalable le corps et les en-têtes dans les variables.
  • GET/POST attendez une réponse dans le fil de script en cours d'exécution. Le temps total pour demander et lire le corps est de 20 secondes. L'arrêt du script annule l'attente ; HTTP_Body/HTTP_Header n'attendez rien. Le corps entier est chargé en mémoire même lorsque FileStream est transféré ; Il ne s’agit pas d’un téléchargement en continu de fichiers volumineux.
  • Le texte est décodé selon le jeu de caractères de la réponse, en l'absence/encodage inconnu - UTF-8. Les réponses HTTP 4xx/5xx sont également lues. Lorsqu'il y a une erreur réseau ou un délai d'attente, le client écrit une erreur, le corps et les en-têtes deviennent vides ; Try/Catch ne remplace pas la vérification de la réponse attendue. L'annulation du script s'étend plus loin. Une erreur d'écriture de fichier local ou d'argument non valide peut être détectée par Try/Catch.
  • POST met à jour le corps et les en-têtes et renvoie le même corps sous forme de chaîne. Ne répétez pas POST automatiquement simplement parce que la réponse est vide : le serveur a peut-être déjà effectué l'action. La vérification d'acceptation/de statut dans les exemples est un accord avec votre service, et non un signe intégré de réussite HTTP.

Scripts C# autonomes

Chaque exemple peut être enregistré dans un fichier séparé .csx et exécuté dans IDE. Les fonctions d'objet UO et d'attente fournissent l'hôte de la session de jeu en cours. Remplacez les noms, coordonnées et adresses de la démo serial par les vôtres.

Exemple simple

Exécutez ce code dans un fichier .csx séparé. Les arguments sont visibles dans l’appel ; remplacez les noms, serials et adresses d’exemple par les vôtres.

Le résultat d’un seul appel est affiché dans le journal. Un nombre n’est pas converti en bool ; un tableau est affiché par son nombre d’éléments.

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

1. Vérifiez la réponse convenue du service - script direct

Paramètres et déroulement de l’exécution :

  • Le service accepte le texte Route arrêtée et, par accord, répond par accepté. Main renvoie true uniquement avec ce texte ; Il s'agit d'une vérification du protocole de votre service, pas d'une vérification du code HTTP.
  • Les adresses example.com sont illustratives et ne fournissent pas un tel service. Remplacez-les par les vôtres ; l'exécution de l'exemple crée une véritable requête HTTP. L'exemple n'effectue pas d'actions de jeu.
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. Envoyer la réponse JSON sérialisée et analyser la réponse JSON - fonction de script

Paramètres et déroulement de l’exécution :

  • System.Text.Json.JsonSerializer échappe aux chaînes du dictionnaire. La valeur d'état est lue après vérification de JSON ; Remplacez l'adresse de démonstration par la vôtre.
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. Enregistrer la réponse jusqu'à la prochaine requête - classe de script

Paramètres et déroulement de l’exécution :

  • firstReply et firstHeaders stockent la réponse POST. Le GET suivant remplace les tampons internes, mais les variables locales contiennent toujours la première réponse.
  • Les adresses example.com sont illustratives et ne fournissent pas un tel service. Remplacez-les par les vôtres ; l'exécution de l'exemple crée une véritable requête HTTP. L'exemple n'effectue pas d'actions de jeu.
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;
    }
}

Implémentation de la commande

C# distingue les majuscules. Utilisez le nom UO exact. Comparez les indicateurs numériques à 0 ; utilisez bool seulement si la signature renvoie bool.

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

Paramètres: url (Any), postData (Any)

Résultat: dynamic / Any.

Pendant un appel:

Code interne de l’implémentation ; ce n’est pas un script autonome.

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

Signatures C#

dynamic UO.Messenger(object? provider);

Crée un objet pour les notifications textuelles et la réception de messages Telegram, Discord ou Viber. Par exemple, le script pourrait signaler la fin de la collecte de ressources ou rechercher une demande d'arrêt émanant d'un utilisateur prédéfini. La création d'un objet ne connecte pas encore le bot et n'envoie rien.

Paramètres

  • provider - string : « télégramme », « discorde » ou « viber » ; le cas n'est pas important. D'autres valeurs provoquent une erreur.

Valeur de retour

Objet Messenger. Ce n'est ni bool ni ID. Les messages ID, les expéditeurs et les chats dans cet objet sont toujours string : comparez-les aux chaînes, ne convertissez pas via Convert.ToInt32/Convert.ToDouble.

Comportement

  • Provider() → string ; Connected() → 1/0 (true/false) : Fournisseur et résultat du dernier contrôle d'autorisation. Connected ne garantit pas la disponibilité d'Internet à ce moment-là.
  • Connect(token) → null : vérifie le jeton du bot ; ConnectFromFile(path) → null : Lit le jeton UTF-8 du fichier jusqu'à 1024 octets. Le chemin relatif est calculé à partir du dossier de script actuel. La reconnexion nécessite Disconnect. Les erreurs peuvent être détectées par Try/Catch.
  • Disconnect() → null : arrête la réception locale, efface le jeton et les curseurs ; l'objet peut être à nouveau connecté. Dispose() → null : ferme complètement l'objet.
  • SendMessage(text, recipient) → string : ID message reçu. Paramètres - chat texte et chaîne ID Télégramme, chaîne ID Discord ou ID abonné Viber. Limites de longueur : 4096/2000/7000 respectivement ; également Viber JSON ≤30000 octets. Le texte vide est interdit. Discord ne crée pas de mentions de tout le monde/rôles.
  • WatchChannel(channelId) → null : Discord, mémorise le dernier message actuel et ne lit que les suivants. WatchChannel(channelId, afterMessageId) → null : commence après la chaîne donnée ID ; "0" inclut l'historique. Jusqu'à 32 canaux par objet.
  • Receive(timeoutSeconds) → Array ; Receive() : 0 délai d'attente. Plage 0..20 secondes ; un tableau vide signifie qu'aucun message texte n'est disponible. Telegram utilise l'interrogation long, Discord interroge les chaînes sélectionnées, Viber lit la file d'attente des webhooks. La requête réseau peut prendre jusqu'à 30 secondes.
  • Chaque MessengerMessage : Id(), SenderId(), SenderName(), ChatId(), Text() → string. Une publication Telegram d'une chaîne peut ne pas avoir SenderId. Les pièces jointes, les événements non textuels et les messages Discord des robots ne seront pas renvoyés.
  • RetryAfter() → int : combien de secondes attendre après avoir limité le service. Avant l'expiration de cette période, les nouvelles requêtes HTTP ne sont pas exécutées. L'envoi après un échec n'est pas répété automatiquement : le serveur peut avoir déjà reçu le message.
  • StartReceiver(localPort, publicHttpsUrl) → int : Viber uniquement ; port 1..65535, renvoie le port local occupé. L'adresse publique HTTPS doit se terminer par /viber/ et transmettre POST à 127.0.0.1:port/viber/ avec le corps d'origine et l'en-tête de signature à l'avance. La méthode enregistre un webhook auprès de Viber.
  • Vous avez besoin d'un jeton de bot, pas d'un mot de passe de compte personnel. Le télégramme avec un webhook existant est rejeté sans le supprimer. Discord nécessite des autorisations de lecture/envoi de chaîne et MESSAGE_CONTENT pour le texte accessible ; Viber envoie aux utilisateurs abonnés.
  • Recevoir enregistre le curseur uniquement après avoir analysé la pile entière. Telegram/Discord renvoie jusqu'à 100 entrées par requête ; appelez à nouveau la réception pour les paquets suivants. Discord sans le deuxième argument WatchChannel ignore l'ancienne histoire.
  • Viber vérifie le HMAC-SHA256 du corps source. File d'attente - Les messages 100 répétés ID sont stockés pour les dernières livraisons 2048 ; le débordement donne HTTP 503 pour une nouvelle tentative par service. Vous avez besoin d'un proxy HTTPS avec Content-Length ; les requêtes fragmentées sur l’entrée locale sont rejetées.
  • Le jeton n'est pas enregistré dans le profil Connect, le texte d'erreur ou l'historique des arguments. Utilisez ConnectFromFile pour éviter de le stocker dans des variables de script visibles par le débogueur. Ne publiez pas de fichiers de jetons.
  • Créez un objet dans une procédure. Pas plus de 32 en même temps ; Utiliser/Dispose le libère plus tôt. Lorsqu'un script se termine, échoue ou s'arrête, tous ses objets messager sont fermés. La fermeture du récepteur Viber ne supprime pas le webhook du service.
  • Il s'agit d'une interface texte : elle n'exécute pas le texte reçu sous forme de code et ne connecte pas les comptes de jeu. Les conditions pour faire confiance à l'expéditeur sont définies par le script lui-même.

Scripts C# autonomes

Chaque exemple peut être enregistré dans un fichier séparé .csx et exécuté dans IDE. Les fonctions d'objet UO et d'attente fournissent l'hôte de la session de jeu en cours. Remplacez les noms, coordonnées et adresses de la démo serial par les vôtres.

Exemple simple

Exécutez ce code dans un fichier .csx séparé. Les arguments sont visibles dans l’appel ; remplacez les noms, serials et adresses d’exemple par les vôtres.

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

1. Télégramme : notification après la fin des travaux - script direct

Paramètres et déroulement de l’exécution :

  • Placez telegram-token.txt à côté du script, remplacez 12345678 par votre chat ID. L'exemple envoie une notification et renvoie la chaîne ID ; recevoir une réponse du serveur ne confirme pas la lecture humaine.
  • Vous avez besoin de vos propres paramètres de bot. Les exemples sont testés avec des réponses aux tests locaux ; ils n'ont pas été envoyés à de vrais utilisateurs.
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 : demande d'arrêt de l'utilisateur sélectionné – Fonction de script

Paramètres et déroulement de l’exécution :

  • Entrez votre chaîne et l'expéditeur autorisé ID. true signifie que ce chèque a reçu le texte stop de sa part ; l’exemple lui-même n’arrête pas le mouvement. Ce résultat peut être utilisé dans votre propre condition de cycle de service.
  • Vous avez besoin de vos propres paramètres de bot. Les exemples sont testés avec des réponses aux tests locaux ; ils n'ont pas été envoyés à de vrais utilisateurs.
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. Charger les paramètres du récepteur à partir du fichier JSON - classe de script

Paramètres et déroulement de l’exécution :

  • System.Text.Json lit le port local/publicUrl. Le jeton est stocké dans un fichier local distinct ; les expéditions réelles ne sont pas effectuées par cet exemple. Le SenderId de confiance est coché, pas le texte entrant arbitraire.
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;
}

Implémentation de la commande

C# distingue les majuscules. Utilisez le nom UO exact. Comparez les indicateurs numériques à 0 ; utilisez bool seulement si la signature renvoie bool.

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

Paramètres: provider (String)

Résultat: dynamic / Object.

Pendant un appel:

Code interne de l’implémentation ; ce n’est pas un script autonome.

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