palworld disocrdから再起動とログイン情報を表示するbot

それだけ

みなさんpalworld遊んでますか?運用してますか?

minecraftとかarkとか運用してた人なら特に問題ないと思います

単純にメモリーの大量消費とバグで再起動が必要になったり色々あるくらいで起動させて友達を呼ぶくらいは問題ないでしょう

今回はうちのサーバで動かしてるdiscord botを紹介します

いろんな人が多機能bot作って公開してるけどそこまでいらんし使いこなせないし好みで修正するの面倒そうだし・・・

chatgptちゃんと作ったので雑に動いてるのもありそうだけどまぁ動いてるからヨシっ

できること

  • discord botのステータスにログインしている人を表示(1分置き)
  • 特定のtextチャンネルで @palserverbot restart でrestart.shを実行して再起動 => 多分再起動の時に通知入れたいとか他の処理したいとかあると思って別ファイルにshellscriptにした

事前準備

  • discord botのtokenを用意
  • botをサーバに招待
  • restartコマンドを実行しても良いdiscord textチャンネルID
  • palserverのrconの許可とパスワードとポート設定
  • サーバでgorcon/rcon-cliを解凍して置いておいてください

修正箇所が複数あるので先に記載

あんまり公開する予定もなかったので色々直で書いてるので修正場所一覧

  • TOKEN = 'ABCDEFGABCDEFGABCDEFG.ABC-AB.ABCDEFGABCDEFGABCDEFGABCDEFGABCDEFG'

disocrd botのTOKENをここに

  • command = "/home/astel/palserverbot/rcon-0.10.3-amd64_linux/rcon -a 127.0.0.1:25575 -p passpass ShowPlayers"

/home/astel/palserverbot/rcon-0.10.3-amd64_linux/rcon をrconがあるdirに修正

passpassをrconのパスワードに変更、portも変更していれば25575からportも変更

  • if message.channel.id == 1234567890 and client.user.mentioned_in(message) and 'restart' in message.content:

restartコマンドを実行しても良いdiscord textチャンネルIDをここに書いてください、特に指定しなくていいよだったら消してもいいですがあったほうがいいです

  • subprocess.run(['/home/astel/palserverbot/restart.sh'], check=True)

restart.shを置いてある場所

  • /home/astel/palserverbot/rcon-0.10.3-amd64_linux/rcon -a 127.0.0.1:25575 -p passpass "Save" (restart.shの方

rcon使ってるのでdirを修正

コードとか

#!/usr/local/src/pyenv/shims/python3

import discord
from discord.ext import tasks
import subprocess
import json

TOKEN = 'ABCDEFGABCDEFGABCDEFG.ABC-AB.ABCDEFGABCDEFGABCDEFGABCDEFGABCDEFG'

Intents = discord.Intents.default()
Intents.members = True

client = discord.Client(intents=Intents)


last_players = []

def get_players():
    command = "/home/astel/palserverbot/rcon-0.10.3-amd64_linux/rcon -a 127.0.0.1:25575 -p passpass ShowPlayers"
    result = subprocess.run(command, shell=True, capture_output=True, text=True)

    output = result.stdout
    lines = output.strip().split('\n')
    players = []

    for line in lines[1:]:
        if line:
            data = line.split(',')
            players.append(data[0])

    return players

@tasks.loop(minutes=1)
async def update_status():
    global last_players
    players = get_players()
    if set(players) != set(last_players):
        if players:
            status_message = ', '.join(players)
        else:
            status_message = 'No players online'
        await client.change_presence(activity=discord.Game(name=status_message))
        last_players = players

@client.event
async def on_ready():
    update_status.start()

@client.event
async def on_message(message):
    print(message.content)
    if message.author.bot:
        return
    if message.channel.id == 1234567890 and client.user.mentioned_in(message) and 'restart' in message.content:
        await message.reply('リスタートの要求を受け付けました。')
        try:
            subprocess.run(['/home/astel/palserverbot/restart.sh'], check=True)
            await message.reply('リスタートしました。')
        except subprocess.CalledProcessError:
            await message.reply('リスタートに失敗しました。管理者にメンションしてください。')

client.run(TOKEN)

restart.sh

#!/bin/bash
set -eu

/home/astel/palserverbot/rcon-0.10.3-amd64_linux/rcon -a 127.0.0.1:25575 -p passpass "Save"
sleep 5s
sudo systemctl stop palworld.service
sleep 10s
sudo systemctl start palworld.service

service

[Unit]
Description=Pal Discord Bot Service
After=network.target

[Service]
Type=simple
User=astel
WorkingDirectory=/home/astel/palserverbot
ExecStart=/usr/local/src/pyenv/shims/python3 /home/astel/palserverbot/pal_discord.py
Restart=on-failure

[Install]
WantedBy=multi-user.target

終わり

メモリ結構つかうしよくわからんタイミングで落ちるしチーターは多いらしいし運用は大変ですね、rconでのコマンドもまだ少ないしホワイトリストもないので

ShowPlayersで取得したものをjsonで処理して1分おきにユーザを見てるので改変すればホワイトリストみたいなものも作れそうだけどチーター目線だと1分あれば拠点破壊は余裕か?

ちなみにShowPlayersでのjsonはこんな形にして処理してるのでsteamidとかuidとかでなんかすれば何かはできそう

[
    {
        "name": "astel",
        "playeruid": "1234567890",
        "steamid": "76561198209561881"
    },
    {
        "name": "erio",
        "playeruid": "9234567891",
        "steamid": "1234567890234556"
    }
]

Twitterみてたらadminパスワードも変更されたりもされてるみたいなのでうーん、IP制限とかまで入れればいけるろうけど面倒だなぁ

チーターだけじゃなくHDD故障もあるしみんなバックアップは取ろう!ちゃんと別のディスクかクラウドに保存するんだぞ!