Portail développeurs
Expérimental La plateforme de bots & d’apps est en développement actif. Les serveurs auto-hébergés font tourner les bots, les commandes slash et les composants de message, avec quelques différences par rapport au cloud. Voir ce qui est pris en charge.
← Docs

Journaux du bot

L’onglet Bot de votre application peut demander au bot en cours d’exécution ses dernières lignes de journal, pour que vous voyiez ce qui s’est passé sans vous connecter à la machine sur laquelle il tourne. Cette page décrit le protocole qu’un bot implémente pour répondre.

Fonctionnement

  1. Un développeur (propriétaire, ou développeur d’équipe ou rôle supérieur) appuie sur Demander les journaux dans l’onglet Bot et choisit une période et un nombre de lignes.
  2. GameVox envoie à votre bot un dispatch gateway nommé GAMEVOX_LOG_REQUEST. Il n’est envoyé qu’aux sessions gateway actives de cette même application.
  3. Votre bot rassemble les lignes de cette période et les envoie par un seul appel REST. Le portail les affiche dès leur arrivée.
  4. Si rien n’arrive dans les deux minutes, le portail indique que le bot n’a pas répondu. Un bot qui ne connaît pas l’événement l’ignore : rien ne casse pour les bibliothèques qui n’en ont jamais entendu parler.

L’événement gateway

Un dispatch ordinaire (opcode 0) avec t défini sur GAMEVOX_LOG_REQUEST. Il porte un numéro de séquence comme tout autre dispatch et est rejoué lors d’une reprise.

{
  "op": 0,
  "s": 4821,
  "t": "GAMEVOX_LOG_REQUEST",
  "d": {
    "request_id": "6f0c2d1e-8a54-4b7e-9c3d-2a1f5e7b9d40",
    "since": "2026-10-30T11:45:00Z",
    "max_lines": 2000,
    "nonce": "3f9a0c...e1b7",
    "expires_at": "2026-10-30T12:02:00Z"
  }
}
  • request_id : identifie la requête ; fait partie de l’URL d’envoi.
  • since : heure RFC 3339. Envoyez les lignes à partir de ce moment.
  • max_lines : le nombre maximal de lignes voulues (de 50 à 20 000). Envoyez les plus récentes si vous en avez davantage.
  • nonce : un secret à usage unique pour cette requête. Renvoyez-le avec l’envoi ; il prouve que l’envoi provient du bot qui a reçu la requête.
  • expires_at : heure RFC 3339 après laquelle l’envoi est refusé (deux minutes après la requête).

Envoyer les lignes

Répondez par une seule requête, authentifiée comme tout autre appel de bot (Authorization: Bot <token>). Le JSON est la forme normale :

POST /api/v10/applications/@me/log-requests/6f0c2d1e-8a54-4b7e-9c3d-2a1f5e7b9d40
Authorization: Bot <token>
Content-Type: application/json

{
  "nonce": "3f9a0c...e1b7",
  "lines": [
    { "ts": "2026-10-30T11:58:02.114Z", "level": "info",  "msg": "synced 12 guilds" },
    { "ts": "2026-10-30T11:58:09.870Z", "level": "error", "msg": "poll failed: timeout" }
  ]
}

HTTP/1.1 204 No Content

Chaque ligne est {ts, level, msg} : ts une heure RFC 3339, level parmi debug, info, warn, error, et msg le texte. Une simple chaîne est acceptée à la place d’un objet.

Le texte brut fonctionne aussi : envoyez Content-Type: text/plain avec une ligne de journal par ligne de texte et le nonce dans un en-tête X-GameVox-Log-Nonce. Les lignes envoyées ainsi n’ont ni horodatage ni niveau (GameVox devine un niveau d’après les mots de la ligne). L’en-tête fonctionne aussi avec le JSON ; le champ du corps n’est qu’une commodité.

Limites et règles

  • Le corps peut faire au plus 2 Mio et une requête conserve au plus 20 000 lignes. Au-delà de la limite de lignes, les plus récentes sont conservées ; un corps plus gros est refusé avec un 413.
  • Une requête ne peut recevoir de réponse qu’une seule fois. Un deuxième envoi reçoit un 409.
  • Seule l’application pour laquelle la requête a été faite peut y répondre. L’id de requête d’une autre application se présente comme un id inconnu (404).
  • L’envoi doit arriver avant expires_at (410 après).
  • Le nonce doit correspondre (403 sinon).
  • Les requêtes sont limitées à une toutes les 30 secondes et à 30 par jour par application. Les lots sont conservés 7 jours puis supprimés.
  • Le texte des journaux est affiché uniquement en texte brut. Les caractères de contrôle sont retirés et chaque ligne est coupée à 4 000 caractères.

Erreurs

  • 400 : le corps n’est pas un JSON valide, ou le nonce est absent.
  • 403 : le nonce ne correspond pas.
  • 404 : cette requête n’existe pas pour votre application.
  • 409 : la requête a déjà reçu une réponse.
  • 410 : la requête a expiré.
  • 413 : le corps dépasse 2 Mio.
  • 429 : votre bot est soumis à une limite de débit comme sur toute autre route.

Retirez les secrets avant l’envoi

Les journaux quittent votre machine, retirez donc ce qui ne doit pas en sortir : votre token de bot et tout autre identifiant, les en-têtes Authorization, les mots de passe dans les URL, les adresses e-mail et les adresses IP de vos utilisateurs. Les bots maison de GameVox font tout cela avant l’envoi.

GameVox masque aussi à l’arrivée (tokens, valeurs Authorization, paires key=value dont la clé désigne un secret, mots de passe dans les URL, longues chaînes hexadécimales et adresses e-mail) et indique à la personne qui consulte combien de valeurs ont été masquées. C’est un filet de sécurité, pas une raison de sauter votre propre masquage : GameVox ne peut pas savoir ce qui est privé dans vos messages.

Exemple

La plupart des bibliothèques vous transmettent les événements qu’elles ne modélisent pas via un hook brut : on_socket_raw_receive dans discord.py, l’événement raw dans discord.js. Conservez les derniers milliers de lignes dans un tampon circulaire et, quand l’événement arrive, envoyez la partie demandée.

# discord.py: keep recent lines, answer GAMEVOX_LOG_REQUEST
import collections, json, logging
from datetime import datetime, timezone

RING = collections.deque(maxlen=5000)

class Ring(logging.Handler):
    def emit(self, record):
        RING.append({"ts": datetime.fromtimestamp(record.created, timezone.utc).isoformat(),
                     "level": record.levelname.lower(),
                     "msg": redact(self.format(record))})

logging.getLogger().addHandler(Ring())

@client.event
async def on_socket_raw_receive(msg):
    packet = json.loads(msg)
    if packet.get("t") != "GAMEVOX_LOG_REQUEST":
        return
    d = packet["d"]
    lines = [l for l in RING if l["ts"] >= d["since"]][-d["max_lines"]:]
    await session.post(
        f"https://app-api.gamevox.com/api/v10/applications/@me/log-requests/{d['request_id']}",
        headers={"Authorization": f"Bot {TOKEN}"},
        json={"nonce": d["nonce"], "lines": lines})

Compatibilité

L’événement est nouveau et facultatif. Les bots écrits avec des bibliothèques Discord continuent de fonctionner sans changement, car un dispatch qu’une bibliothèque ne connaît pas est ignoré. Les bots maison de GameVox (League of Legends, VALORANT, Deadlock, Valheim, WARDOGS, guilde WoW, Tickets et Tibia) le prennent en charge via la bibliothèque de bots partagée.

← Toute la doc