LoginSignup
0
0

パルワールドサーバー の Discord Bot を作ってみた

Last updated at Posted at 2024-02-25

概要

パルワールドサーバー を 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 となっています

restart.jpg

help コマンド (どんなコマンドが使えるか)

諸々のセットアップが済んだ状態で、
/help と打つと、コマンドの一覧が表示されます

help.jpg

info コマンド

/info で サーバー情報(バージョン等) が表示されます

info.jpg

上記で 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アカウント作成

OAuth2 URL Generator から、Bot の権限を付与した URL を生成します

  • MESSAGE CONTENT INTENT が有効になっていて、
  • Bot Permissions
    • Send Messages
    • Read Message History
    • Read Messages/View Channels

になっていることを確認してください
トークンを後で利用するので、メモしておきます

bot-permission.jpg

Webhook作成

Webhookは、チャンネルに対して作成されます

ウェブフックURLを後で利用するので、メモしておきます

webhook-setting.jpg

rcon-py 構築前準備1

.env に 上記でメモした情報を記載します

.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}```")

status.jpg

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

info2.jpg

毎朝 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 かどうかで判定する方式にしてみました

上記のように、ちょっと変わった実装になってるので、
もし、このツールを使ってみようと思っていただけた場合、
コマンドの実行を正しく制限できてるか、注意してみてください

参考

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0