開発者ポータル
試験運用中 ボット&アプリ基盤は現在も活発に開発中です。セルフホストサーバーでも、ボット、スラッシュコマンド、メッセージコンポーネントが動作します(クラウドとはいくつか違いがあります)。対応状況を見る。
← ドキュメント

ボットのログ

アプリケーションの Bot タブから、実行中のボットに最近のログ行を要求できます。ボットが動いているマシンにログインしなくても、何が起きたかを確認できます。このページでは、ボットが応答するために実装するプロトコルを説明します。

仕組み

  1. 開発者(オーナー、またはチームの開発者以上)が Bot タブでログを要求を押し、期間と行数を選びます。
  2. GameVox はボットに GAMEVOX_LOG_REQUEST という名前のゲートウェイ配信を送ります。配信先は、同じアプリケーションの接続中のゲートウェイセッションだけです。
  3. ボットはその期間のログ行を集め、REST 呼び出し 1 回でアップロードします。ポータルは届いた時点ですぐに表示します。
  4. 2 分以内に何も届かなければ、ポータルはボットが応答しなかったと表示します。このイベントを知らないボットは無視するだけなので、このイベントに対応していないライブラリでも何も壊れません。

ゲートウェイイベント

t が GAMEVOX_LOG_REQUEST の、通常の配信(オペコード 0)です。他の配信と同じくシーケンス番号を持ち、再開(resume)時には再送されます。

{
  "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: リクエストの識別子。アップロード先 URL の一部になります。
  • since: RFC 3339 の時刻。この時刻以降の行を送ってください。
  • max_lines: 求める最大行数(50〜20,000)。それより多くある場合は新しいものを送ってください。
  • nonce: このリクエスト専用の使い捨てのシークレット。アップロード時に送り返してください。リクエストを受け取ったボットからのアップロードであることの証明になります。
  • expires_at: これを過ぎるとアップロードが拒否される RFC 3339 の時刻(リクエストの 2 分後)。

ログ行をアップロードする

他のボット呼び出しと同じ認証(Authorization: Bot <token>)で、1 回のリクエストで応答します。通常は JSON 形式です:

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

各行は {ts, level, msg} です。ts は RFC 3339 の時刻、level は debug、info、warn、error のいずれか、msg は本文です。オブジェクトの代わりに単なる文字列も受け付けます。

プレーンテキストも使えます。Content-Type: text/plain で 1 行ずつ送り、nonce は X-GameVox-Log-Nonce ヘッダーに入れてください。この方法で送った行にはタイムスタンプもレベルも付きません(GameVox が行内の単語からレベルを推測します)。このヘッダーは JSON でも使えます。ボディのフィールドは便宜上のものにすぎません。

上限と規則

  • ボディは最大 2 MiB で、1 つのリクエストで保持されるのは最大 20,000 行です。行数の上限を超えた場合は最新の行が残ります。サイズの上限を超えるボディは 413 で拒否されます。
  • リクエストに応答できるのは 1 回だけです。2 回目のアップロードには 409 が返ります。
  • 応答できるのはリクエストの対象となったアプリケーションだけです。別のアプリケーションのリクエスト ID は、不明な ID と同じに見えます(404)。
  • アップロードは expires_at より前に届く必要があります(過ぎると 410)。
  • nonce が一致する必要があります(一致しなければ 403)。
  • リクエストはアプリケーションごとに 30 秒に 1 回、1 日 30 回までです。バンドルは 7 日間保存された後に削除されます。
  • ログのテキストはプレーンテキストとしてのみ表示されます。制御文字は取り除かれ、各行は 4,000 文字で切り詰められます。

エラー

  • 400: ボディが正しい JSON ではないか、nonce がありません。
  • 403: nonce が一致しません。
  • 404: このアプリケーションに該当する要求はありません。
  • 409: リクエストにはすでに応答済みです。
  • 410: リクエストの期限が切れています。
  • 413: ボディが 2 MiB を超えています。
  • 429: 他のルートと同じく、ボットがレート制限を受けています。

送信前にシークレットを取り除く

ログはあなたのマシンの外へ出るので、出してはいけないものは取り除いてください。ボットトークンやその他の資格情報、Authorization ヘッダー、URL 内のパスワード、メールアドレス、ユーザーの IP アドレスなどです。GameVox のファーストパーティボットは、アップロード前にこれらをすべて取り除いています。

GameVox も受信時に秘匿処理を行い(トークン、Authorization の値、キー名がシークレットを示す key=value の組、URL 内のパスワード、長い 16 進文字列、メールアドレス)、いくつの値を隠したかを閲覧者に伝えます。これは安全網であって、自分での秘匿処理を省いてよい理由にはなりません。メッセージの中の何が非公開かは GameVox にはわからないからです。

例

ほとんどのライブラリは、モデル化していないイベントを生のフック経由で渡します。discord.py では on_socket_raw_receive、discord.js では raw イベントです。直近の数千行をリングバッファに保持しておき、イベントが届いたら要求された範囲を送ってください。

# 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})

互換性

このイベントは新しく、対応は任意です。ライブラリは知らない配信を無視するため、Discord のライブラリで書かれたボットは変更なしでそのまま動きます。GameVox のファーストパーティボット(League of Legends、VALORANT、Deadlock、Valheim、WARDOGS、WoW ギルド、Tickets、Tibia)は、共通のボットライブラリを通じて対応しています。

← すべてのドキュメント