概要
パルワールドサーバー を Discord のチャット経由 で操作できるように、
Discord Bot (rcon-py) を作成しました
この記事は、上記リポジトリの使い方や仕組みについて
ざっくりまとめた備忘録となります
前提
この記事は、パルワールドサーバーの構築とデーモン化
の作業が前提になっています
- パルワールドサーバーの構築とデーモン化
ディレクトリ構成も、以下のように
/home/steam/dedicated-server/palworld になっていることを想定しているので、
別のディレクトリ構成で実行させる場合、適宜修正してください
# base directories
SRC_DIR = os.path.dirname(__file__)
HOME_DIR = "/home/steam"
INSTALL_DIR = f"{HOME_DIR}/dedicated-server/palworld"
# logging settings
LOG_PATH = f"{SRC_DIR}/logs/app.log"
DEBUG_LOG_PATH = f"{SRC_DIR}/logs/debug-app.log"
# server settings
BANLIST_PATH = f"{INSTALL_DIR}/Pal/Saved/SaveGames/banlist.txt"
CONFIG_PATH = f"{INSTALL_DIR}/Pal/Saved/Config/LinuxServer/PalWorldSettings.ini"
DEFAULT_CONFIG_PATH = f"{INSTALL_DIR}/DefaultPalWorldSettings.ini"
rcon-py とは何者か
Discord のチャット経由で
サーバ運用に必要な色々なコマンドを投入できる Bot となっています
help コマンド (どんなコマンドが使えるか)
諸々のセットアップが済んだ状態で、
/help と打つと、コマンドの一覧が表示されます
info コマンド
/info で サーバー情報(バージョン等) が表示されます
上記で rcon-py が何者かなんとなく理解いただけたと思うので、
- rcon-py の仕組み
- Discord Bot を作るための準備
について掘り下げていきます
rcon-py の仕組み
主に下記の2つで構成されます
- discord.py
- python で実装された Discord用のAPIラッパー です
- rcon(gorcon/rcon)
- go で実装された rcon cli ツールです
Discord Bot を作るための準備
今回は Bot と Webhook の両方を利用するので、下記などを参考に、
それぞれ作成して、認証に必要な情報をメモしておきます
- Botアカウント作成
-
https://discordpy.readthedocs.io/ja/latest/discord.html
- DISCORD_BOT_TOKEN
-
https://discordpy.readthedocs.io/ja/latest/discord.html
- Webhook作成
-
https://support.discord.com/hc/ja/articles/228383668
- DISCORD_WEBHOOK_URL
-
https://support.discord.com/hc/ja/articles/228383668
Botアカウント作成
OAuth2 URL Generator から、Bot の権限を付与した URL を生成します
- MESSAGE CONTENT INTENT が有効になっていて、
- Bot Permissions
- Send Messages
- Read Message History
- Read Messages/View Channels
になっていることを確認してください
トークンを後で利用するので、メモしておきます
Webhook作成
Webhookは、チャンネルに対して作成されます
ウェブフックURLを後で利用するので、メモしておきます
rcon-py 構築前準備1
.env に 上記でメモした情報を記載します
ALLOWED_USERS="user1,user2,user3"
ALLOWED_ROLES="Admin,ServerAdmin"
DISCORD_BOT_TOKEN="xxxxx"
DISCORD_WEBHOOK_ID='xxxxx'
DISCORD_WEBHOOK_URL='https://discord.com/api/webhooks/xxxxx/yyyyy'
rcon-py の権限について補足
このチャットボットを実行できるユーザを制限しています
下記3つのいずれかの条件を満たす場合、コマンドを実行できます
- 特定のユーザ(ALLOWED_USERS) であるか
- 特定のロール(ALLOWED_ROLES) に属しているか
- 特定のウェブフック(DISCORD_WEBHOOK_ID) であるか
rcon-py 構築前準備2
rcon.yaml に RCON の認証情報を定義しておきます
PalWorldSettings.ini を
RCONEnabled: TRUE
RCONPort: 25575
に設定している場合、以下のようになります
palworld:
address: "localhost:25575"
password: "hoge"
rcon-py 構築
- 構築
make
- 破棄
make clean
Makefile
Makefile に
all(venv, unit, cron, rcon, start), clean を定義しています
make で実行することで、それぞれの処理を実行できます
venv
既存の python を汚したくないので、
python3 の venv 環境を作成して venv に対して、
requirements.txt に記載されたパッケージをインストールします
unit
etc/systemd/system/rcon-py.service を
/etc/systemd/system/rcon-py.service にコピーします
cron
etc/cron.d/rcon-py を /etc/cron.d/rcon-py にコピーします
rcon
gorcon/rcon リポジトリから rcon cli を入手し、
/usr/local/bin/rcon にコピーします
src/app.py
Bot の本体です
上記の info コマンドは、以下のように実装されています
is_valid_request で
構築前準備1, 構築前準備2 で設定した情報を元に、
許可されたリクエストかどうかを判定しています
@bot.command(name="info", brief="サーバーの情報を表示します")
@is_valid_request()
async def info(ctx):
result = run_rcon_command("Info")
if result.returncode == 0:
await ctx.send(f":ok: Info に成功しました\n```{result.stdout}```")
else:
await ctx.send(f":warning: Info に失敗しました\n```stdout: {result.stdout}\nstderr: {result.stderr}```")
status コマンド
/status で サーバーの状態を表示します
ローカルホストで systemctl status palworld を直接実行しています
/stop, /start, /restart なども同様に実装されています
@bot.command(name="status", brief="サーバーの状態を表示します")
@is_valid_request()
async def status(ctx):
result = subprocess.run(["systemctl", "status", "palworld"], capture_output=True, text=True)
msg = truncate_message(result.stdout)
await ctx.send(f"```# systemctl status palworld\n{msg}```")
src/hook.py
webhook 実行用のスクリプトです
ウェブフック経由で /info を実行する場合、以下のようになります
[root@game-server 17:48:49] rcon-py # pwd
/root/repos/rcon-py
[root@game-server 17:48:50] rcon-py # source venv/bin/activate
(venv) [root@game-server 17:48:56] rcon-py # src/hook.py info
app.py の logger
app.py では logging で app.log に出力しています
hook.py 実行時も何も出ませんでしたが、チャンネルへの出力と、
src/logs/app.log のログが出力されています
[root@game-server 17:48:36] logs # tail -f src/logs/app.log
...
[2024-02-25 17:49:03] [INFO ] app.py: [on_message] message.content: /info
[2024-02-25 17:49:03] [INFO ] app.py: [on_message] message.webhook_id: 1200200034006780000
[2024-02-25 17:49:03] [INFO ] app.py: [logging_command] cmd: 'info' args: []
[2024-02-25 17:49:03] [INFO ] app.py: [on_message] message.content: :ok: Info に成功しました
\```Welcome to Pal Server[v0.1.4.1] Teityura's Palworld Server
\```
[2024-02-25 17:49:03] [INFO ] app.py: [on_message] message.webhook_id: None
毎朝 6:55 に再起動させる cron ジョブ
etc/cron.d/rcon-py を下記のように書くと、
毎日 am 6:55 に /restart を実行するようになります
55 6 * * * @@CUR_USER@@ @@CURDIR@@/venv/bin/python @@CURDIR@@/src/hook.py restart 300
その他メモ
コンテナで環境を分離したい
RCON で 対応したコマンドを実行するだけのツールにしたかったのですが、
「デーモンの再起動や、banlist.txt の編集等が必要になるな」と思い、
「じゃあ、paramikoでSSH経由でコマンドを流す感じになるかな?」と思い、
「実装とかエラー処理が面倒そうだな。。」と思い、コンテナでの実装を断念しました
でも構築は楽にしたい
docker-compose up -d とかで環境立ち上がるのが好きです
venv の構築とか、
unit, cron の設定とかが、
ワンコマンドでできたら嬉しいけど、
シェル書くのもなんかアレやなーと思いました
なので、Makefile でそれらを実行できるようにしてみました
make コマンドってなんか気持ちいいですね
gorcon/rcon を使わせてもらってる理由
python のモジュールで RCON を使えるものをいくつか試したのですが、
自分の環境では、コマンドの実行はできるが、
タイムアウトが発生したりして、うまくいかなかったので、
じゃあ rcon cli 使えばいいかな?と思い、
よさげな記事が見つかったので、同じ感じで実装してみました
多分、やりませんが、 余力があれば、
RCONの部分も自分で実装してみたいなーと思ってます
他のBotも実装したい
ARK, Minecraft, 7d2d など、
他の色々なゲームサーバーのBotで運用できるようになったらいいなー、と頭の片隅に置いておきつつ、
結果、パルワールドだけの実装になってます
rcon cli は
rcon -e palworld のようにプロファイルを切り替えれるので、
app.py を ゲームごとに分離できれば、統合とかもできるかなーと思ったりします
全てのゲームサーバのBotを統合するべきかどうかは、
また今度考えることにしますが、
パルワールド以外のBotを作る場合も、多分同じ感じで作れると作れるかなと思います
コマンドの定期実行について
hook.py で ウェブフックユーザとして、チャットをして、
そのチャット内容に対して、コマンドを実行するようにしています
app.py に定義したコマンドを実行する方法について調べたところ、
asyncio で特定時間になれば、
特定のメソッドを定期実行する方法などが見つかりました
app.py は
チャンネルの監視, 対応したコマンドの実行 だけをやらせたかったので、
DISCORD_WEBHOOK_ID かどうかで判定する方式にしてみました
上記のように、ちょっと変わった実装になってるので、
もし、このツールを使ってみようと思っていただけた場合、
コマンドの実行を正しく制限できてるか、注意してみてください
参考
- Discord botからEC2で建てたPalWorldサーバーを管理する
-
https://zenn.dev/geny7i/articles/7259b1b53f445a
- BOTのトークンや実装のベースの参考にしました
-
https://zenn.dev/geny7i/articles/7259b1b53f445a
- gorcon/rcon
-
https://github.com/gorcon/rcon
- これを /usr/local/bin/rcon に設置します
-
https://github.com/gorcon/rcon
- rcon-py
-
https://github.com/teityura/rcon-py
- 今回の成果物です
-
https://github.com/teityura/rcon-py