【discord.py】デバッグツールJishakuを使ってみる

# はじめに

`discord.py`のデバッグ/実験のための拡張機能`Jishaku`の簡単なインストール方法と使い方を紹介します。

## この記事の対象者

- ある程度`discord.py`の知識があり、拡張機能の`Jishaku`を使ってみたい。

## 前提知識

- 基本的なPythonの記法と`discord.py`の仕様を理解している

# 実装

`Jishaku`は`discord.py`とは別に`pip`または`pip3`でインストールする必要があります。

## インストール

```bash:shell
pip install -U jishaku
```

## 導入

botのコードの任意の箇所で`discord.ext.commands.Bot.load_extension('jishaku')`を実行します。おすすめは`@bot.event`の`on_ready()`の中です。
```python:main.py
import discord
from discord.ext import commands


intents = discord.Intents.all()
bot = commands.Bot(command_prefix='.', intents=intents)


@bot.event
async def on_ready():
    await bot.load_extension('jishaku') # 追加
    print(f'Logged in as {bot.user}')


bot.run(TOKEN)
```

# 使い方

botを動かすことに成功したら早速使ってみましょう。

## コマンド

`commands.Bot()`で指定した`command_prefix`引数の値に加えて`jishaku`または`jsk`と入力することで呼び出せます。
ここでは例として`command_prefix`に`.`を指定していますが、異なる値を指定していれば適宜置き換えてください。

### `jsk`

引数を何も指定しないときはbotの情報などを表示してくれます。
```text
User:
.jsk

Bot:
Jishaku v2.5.2, discord.py `2.3.2`, `Python 3.10.14 (main, Mar 19 2024, 21:46:16) [GCC 13.2.0]` on `linux`
Module was loaded <t:1717636189:R>, cog was loaded <t:1717636189:R>.

This bot is not sharded and can see 33 guild(s) and 1455 user(s).
Message cache capped at 1000, presences intent is enabled, members intent is enabled, and message content intent is enabled.
Average websocket latency: 282.09ms
```

### `jsk [py|python] <argument>`, `jsk [pyi|python_inspect] <argument>`

後ろに続くPythonコードを実行,評価します。
```text
User:
.jsk py 3 + 5

Bot:
8
```
このコマンドでは以下の予約された変数が利用可能です:
| **変数** | **説明** |
|-----|-----|
| `_ctx`              | 呼び出されたコマンドの [Context](https://discordpy.readthedocs.io/ja/latest/ext/commands/api.html#discord.ext.commands.Context).|
| `_bot`              | 実行中の [Bot](https://discordpy.readthedocs.io/ja/latest/ext/commands/api.html#discord.ext.commands.Bot) インスタンス.|
| `_author`<br>`_channel`<br>`_guild`<br>`_me`<br>`_message`<br>`_msg` | [`_ctx`](https://discordpy.readthedocs.io/ja/latest/ext/commands/api.html#discord.ext.commands.Context)の属性のショートカット.|
| `_find`<br>`_get`   | [`discord.utils`](https://discordpy.readthedocs.io/ja/latest/api.html#utility-functions) 関数のショートカット. |
```text
User:
.jsk py _ctx.channel

Bot:
<TextChannel id=1004384431919865927 name='bot-command' position=8 nsfw=False news=False category_id=1004380105679835167>
```

### `jsk [dis|disassemble] <argument>`

このコマンドは非同期コンテキストで引数Pythonコードをコンパイルし、その結果の関数を`dis.dis`の形でPythonのバイトコードに逆アセンブルします。コード自体は実行されません。
```py
User:
.jsk dis print("Hello, World!")

Bot:
               0 GEN_START                1

  -9           2 LOAD_GLOBAL              0 (print)
               4 LOAD_CONST               1 ('Hello, World!')
               6 CALL_FUNCTION            1
               8 RETURN_VALUE
```

### `jsk ast <argument>`

このコマンドはPythonコードを抽象構文木にコンパイルし、ASTブロックのフォーマットされたツリーとして表示します。
```ansi
User:
.jsk ast print("Hello, World!")

Bot:
Module
┣ body[0]: Expr
┃          ┗ value: Call
┃          ┊        ┣ func: Name
┃          ┊        ┃       ┣ id: 'print'
┃          ┊        ┃       ┗ ctx: Load
┃          ┊        ┣ args[0]: Constant
┃          ┊        ┃          ┣ value: 'Hello, World!'
┃          ┊        ┃          ┗ kind: None
┃          ┊        ┗ keywords: []
┗ type_ignores: []
```

### `jsk [sh|shell] <argument>`

このコマンドはシステムシェル内のコマンドを実行します。
`Linux`でカスタムシェルを使用している場合、`jishaku`は環境変数`SHELL`に従います。
`Windows`の場合、`PowerShell`が検出されればそれを使用し、検出されなければコマンドプロンプトを使用します。
渡されたコマンドの結果は、コマンドの実行と同時に、ページネーターインターフェイスを通じて動的に返されます。コマンドを停止する必要がある場合は、停止ボタンを押すか、`jsk cancel`を使用してください。`120`秒間出力がなければ、実行は自動的に終了します。
```shell
User:
.jsk sh curl "http://127.0.0.1:8080"

Bot:
$ curl "http://127.0.0.1:8080"

[stderr]   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
[stderr]                                  Dload  Upload   Total   Spent    Left  Speed
[stderr]   0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0100     9  100     9    0     0   5379      0 --:--:-- --:--:-- --:--:--  9000
It works!

[status] Return code 0
```

### `jsk git <argument>`, `jsk pip <argument>`

よく使われるシェルコマンドのショートカット。
```shell
User:
.jsk pip --version

Bot:
$ pip --version

pip 24.0 from /nix/store/xxx-python3.10-pip-24.0/lib/python3.10/site-packages/pip (python 3.10)

[status] Return code 0
```

### `jsk [load|reload] [extensions...]`, `jsk unload [extensions...]`

これらのコマンドは、Botに拡張機能をロード、リロード、アンロードします。
`jsk reload jishaku`で`jishaku`自体をリロードできます。
`jsk reload ~`はBotのすべての拡張機能をリロードします。
`jsk reload cogs.one cogs.two`は複数の拡張機能を一度にロード、リロード、アンロードできます。
```text
User:
.jsk reload jishaku

Bot:
🔁 `jishaku`
```

### `jsk shutdoun`

このコマンドはBotを強制的にシャットダウンさせます。
```text
User:
.jsk shutdown

Bot:
Logging out now…
```

### `jsk rtt`

このコマンドはAPIへのBotの[ラウンドトリップタイム](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%82%A6%E3%83%B3%E3%83%89%E3%83%88%E3%83%AA%E3%83%83%E3%83%97%E3%82%BF%E3%82%A4%E3%83%A0)を計測します。
```text
User:
.jsk rtt

Bot:
Calculating round-trip time...

Reading 1: 462.69ms
Reading 2: 589.30ms
Reading 3: 396.35ms
Reading 4: 359.84ms
Reading 5: 415.61ms

Average: 444.76 ± 88.91ms
Websocket latency: 282.64ms
```

### `jsk sync [guild_ids...]`

このコマンドは`app_command`ツリーをサーバーのリストに対して同期させ、サーバーがない場合はグローバルに同期させ、その結果を表示します。
```text
User:
.jsk sync 1035868070181175328 1205753507601191993

Bot:
📡 `1035868070181175328` Synced 0 guild commands
📡 `1205753507601191993` Synced 0 guild commands
```

### `jsk cat <file>`

このコマンドはファイルシステムからファイルを読み込み、自動的にエンコードを検出し、(該当する場合は)ハイライト表示します。Botのログやプロジェクトのソースファイルなどを読み込むのに使用できます。
```text
User:
.jsk cat log.txt

Bot:
[some kind of log...]
```

### `jsk curl <url>`

このコマンドはURLからテキストを読み込み、`jsk cat`と同様にエンコードと言語の検出を試ます。
例えば、メッセージが長すぎる場合に作成される`message.txt`ファイルや、貼り付けられたサイトの生ファイルなど、オンライン上のファイルの内容を表示するのに使うことができます。
```text
User:
t.jsk curl "http://127.0.0.1:8080"

Bot:
It works!
```

### `jsk exec [member and/or channel...] <command string>`, `jsk debug <command string>`, `jsk repeat <times> <command string>`

これらのコマンドは、他のコマンドのコマンドコントロールとして機能します。
`jsk exec`を使用すると、別のユーザー、別のチャンネル、またはその両方としてコマンドを実行できます。後置感嘆符付きのエイリアス(`jsk exec! ...`など)を使用するとチェックやクールダウンをバイパスしてコマンドが実行できます。
`jsk debug`は、例外ラッパーとタイマーを使ってコマンドを実行します。これにより再現可能なコマンドエラーや速度低下に関するフィードバックを素早く得ることができます。
`jishaku repeat`は、コマンドを指定された回数だけ繰り返します。
```text
User:
.jsk repeat 5 jsk py import time;time.time()

Bot:
1717641462.6427937
1717641463.736665
1717641464.8076453
1717641464.8076453
1717641467.1348138
```

### `jsk permtrace <channel> [targets...]`

このコマンドを使用すると、指定されたチャネルで指定された権限のソースを調査できます。対象はメンバー、またはロールのリスト(これらのロールを持つメンバをシミュレートするため)です。
このコマンドは指定されたメンバーまたはロールのサーバー権限とチャンネルオーバーライトをすべて読み込み、権限が許可されているかどうかとその最も基本的な理由を含む内訳を提供します。
```text
User:
.jsk permtrace 1004383431919865937

Bot:
This is the permissions calculation for the following targets in ⁠bot-command:

Please note the reasons shown are the most fundamental reason why a permission is as it is. There may be other reasons that persist these permissions even if you change the things displayed.
...
✅ add_reactions (because it is the server-wide @everyone permission)
✅ attach_files (because it is the server-wide @everyone permission)
✅ change_nickname (because it is the server-wide @everyone permission)
(以下省略)
...
❌ ban_members (because it is the server-wide @everyone permission)
❌ deafen_members (because it is the server-wide @everyone permission)
❌ kick_members (because it is the server-wide @everyone permission)
(以下省略)
```

# 終わりに

最後まで読んで頂きありがとうございます。不備があれば是非コメントで指摘して下さい。