見出し画像

DiscordBotでMinecraftサーバーを動かそう!!

前書き

前回の記事の一応続きとなってますので、見て頂けると幸いです。

環境はraspberry pi4 8GBのubuntu server 21.10です。
マイクラサーバーしか使ってません。もったいなさすぎかも~🦆
今回の『Discordで動かそう』というのは、あまりにもサーバーに人が入っていない時間が多すぎる🤷!!
なので常時開放という形ではなく、参加者にサーバーの開放を任せた方が良いのではと思い立ち、作成することにしました。
逐一開けろって?めんどい。

今回もやりながら書きながら進めているため、見切り発車ですがDiscordBot自体は作成した経験があるので、どうにかなると思います🥴

用意する物

・Minecraftサーバーを開けるRaspberry pi
・PC(今回はwin10)
・時間(大体1日くらい)

SSHとか英語でかっこつけてんじゃねー!!!

なんかよく知りませんがSSHってやつをやります。
他のデバイスで操作することができるみたいです。

ラズパイ編

まずはOpenSSHServerとやらをインストール。

sudo apt install openssh-server
sudo apt upgrade

動いているか確認します。

sudo systemctl status ssh
相も変わらず直撮り

緑色でactiveとなっているので、動いていますね。

次はファイアウォールを設定します。

sudo ufw allow ssh

確認もしましょう。

sudo ufw status

25565は前回設定したマイクラ用の穴ですので、22/tcpがsshの穴ですね。
(先に確認していなかったので自信が……。)

 sshを開きます。(開くで合ってるのか??)
私はip固定をしていますが、わからない人はip aで確認しましょう。

ssh ubuntu@192.168.~.~

ubuntuはユーザー名、192.168.~.~はipアドレスです。
接続するかどうか聞かれるのでyesを入力。
そしたらパスワードを設定します。
これでラズパイ編、完。

PC編

sshで操作するための設定をします。(私の環境はwin10です。)
ソフトは色々ありますが、Tera tarmは正直あまり好きではないので、今回はPoderosaを使用します。
まずはダウンロード。

zipを解凍してexeを実行します。

真っ新に生まれ変わって人生一から始めたPoderosa

ファイル→新規Telnet/SSH接続を選択。

選択したら新規セッションが出てきます。
ホストにipアドレス、アカウントにユーザー名、パスフレーズに設定したパスワードを入れ、OKを押します。
すると……

■がラズパイの情報、●がPCの情報を表しています

PCでラズパイが動かせちゃいます!!
(同一LANにいる場合のみです。)
これで直撮りしないで済む。
もしsshを切りたいときはsudo systemctl stopで止められます。

圧倒的さぎょらく……!!
いちいちPCで調べながらラズパイでコード書くとかやらずに、コピーで解決できちゃう世界になりました。一番最初にやっとくべきとか言わないで。
サブタイトルにはかっこつけてんじゃねー!!!と書きましたが、結果かっこつけるだけのメリットを感じます。
すげーぜ……SSH……!!

DiscordBotを作っちゃお~~~!

外見だけ

まずはこいつにログイン。

スクショのためにわざわざゲストでやってやったさ

右上のNew Applicationを押しまして、nameを入れます。(Botの名前)

今日から君は、鯖Botだ!

Bot→Add Botと進みます。

なんか出てきますがyes押したら、Bot君できました。

初期アイコンでかわいい💛

TOKENというのが大事です。ここにあることを覚えておき、また誰にも教えてはいけない事を誓ってください。神に。
ある事情でキリスト教はあまり好きではないですが……。

OAuth2のURLGeneratorでSCOPESはbotにチェックを、BOTPERMISSIONSにはbotに与える権限を選択してください。
私はAIの反逆が強いのでメッセージの送信しかやらせません。

権限が無さすぎて可哀想な鯖Bot君……

権限を選んだら一番下に出てくるURLを踏んで、入れたいサーバーを選択してください。
(権限が無いとサーバーにBotを入れられないので、権限がないなら権限のある方に入れてもらいましょう。)

サーバーに入ったらこのようになります。

オフライン鯖Bot君

あとでTOKENを取りに戻ってくるのでタブは残しておきましょう。

やっぱ何事も中身が大切

ということで中身を書いていきます。
6時間くらい試してやっとうまくいきました。
私の成果、ぜひ見てくれよな!!

マイクラサーバー用のフォルダにDiscordのプログラムをpythonで書きます。
(msdis = minecraft server discordの略)

cd ms1.18
sudo pip install discord.py
nano msdis.py

msdis.pyの中身は何となく触れていきます。
いや、触れさせて!!力作なの!!!

import discord
import os
import time

TOKEN = 'DISCORD-TOKEN'

client = discord.Client()

まずは基本部分。これがないとやってられない。
importで必要なライブラリを入れます。
TOKENの部分はシングルコーテーション(')内をDiscordBotのTOKENに置き換えてください。
clientで接続のためのオブジェクト生成を行います。

@client.event
async def on_ready():

    print('ログインしました')

起動時に実行する部分です。
起動に成功するとterminalにログインしましたと表示します。

@client.event
async def on_message(message):

    if message.author.bot:
        return

メッセージの受信時に動作する処理で、メッセージの送信者がBotの場合は無視するように設定。

ここからはコマンド処理部になります。

if message.content == '!command':
        f = open('command.txt', 'r')
        await message.channel.send(f.read())
        f.close()

Discordで!commandを入力したら、command.txtを表示するプログラム。
command.txtの中身はこんな感じ。

!command - コマンド表示
!start   - サーバー起動
!stop    - サーバー停止
!save    - ワールド保存
!status  - サーバー状況

インデントが綺麗……。
だけど表示されるときはインデントありませんでした。チクショ~~~~~~!!!!!!

    if message.content == '!start':
        if os.system('systemctl is-active ms') == 0:
            await message.channel.send('Server - OPEN')
        else :
            await message.channel.send('wait a minute...')
            os.system('systemctl start ms')
            time.sleep(90)
            await message.channel.send('Server - OPEN')

起動コマンド!startです。
開いてるときには開けません。えらい。
ms.serviceを起動しています。

    if message.content == '!stop':
        if os.system('systemctl is-active ms') == 0:
            await message.channel.send('wait a minute...')
            os.system('systemctl stop ms')
            time.sleep(90)
            await message.channel.send('Server - CLOSE')
        else :
            await message.channel.send('Server - CLOSE')

停止コマンド!stopです。
!startの開けるを閉じるに変えただけです。パクリ。

    if message.content == '!save':
        if os.system('systemctl is-active ms') == 0:
            os.system('systemctl start ms-save.service')
            await message.channel.send('world saved.')
        else :
            await message.channel.send('Server - CLOSE')

保存コマンド!saveです。
保存するためのsave.shを動かしてもなぜかうまくいかなかったため、わざわざms-save.serviceを作りました。
(ms-save.serviceの説明は次の章でします。)
閉じているときに保存はできません。

    if message.content == '!status':
        if os.system('systemctl is-active ms') == 0:
            await message.channel.send('Server - OPEN')
        else :
            await message.channel.send('Server - CLOSE')

状況確認コマンド!statusです。
先程からのコマンドでサーバーの開閉がどちらか判定している部分は、systemctl is-active ms(ms.serviceがactiveの際に0を返す)で判定しています。
os.systemというのは、pythonでtarminalへコマンドを打つ関数です。

!sayでマイクラサーバーにメッセージを送信しようとしたのですが、コマンドで受け取った内容を送信するプログラム内に反映するのが難しく、断念しました。

sedコマンドやpythonでシェルの中身を編集して実行、といったものを何個か書きましたが、どうもうまくいきませんでした。
きったねえプログラムですが、コマンドを2つに分けて中に無理やりメッセージを入れ込んだりもしました。

時間がなくてできませんでしたが、sedコマンドを.serviceで動かせばうまくいったかも。
(その場合だとテキストファイルをpythonで出力して、そこからsedコマンドでシェルに実装して起動、みたいな感じかな???)
まあめんどくさいのでやらないと思います。

client.run(TOKEN)

最後にBotの起動とDiscordサーバーへの接続です。
pythonはインデントが大事なので、全部まとめたやつも載せておきます。

import discord
import os
import time

TOKEN = 'DISCORD-TOKEN'

client = discord.Client()

@client.event
async def on_ready():
    print('ログインしました')

@client.event
async def on_message(message):
    if message.author.bot:
        return

    if message.content == '!command':
        f = open('command.txt', 'r')
        await message.channel.send(f.read())
        f.close()

    if message.content == '!start':
        if os.system('systemctl is-active ms') == 0:
            await message.channel.send('Server - OPEN')
        else :
            await message.channel.send('wait a minute...')
            os.system('systemctl start ms')
            time.sleep(90)
            await message.channel.send('Server - OPEN')

    if message.content == '!stop':
        if os.system('systemctl is-active ms') == 0:
            await message.channel.send('wait a minute...')
            os.system('systemctl stop ms')
            time.sleep(90)
            await message.channel.send('Server - CLOSE')
        else :
            await message.channel.send('Server - CLOSE')

    if message.content == '!save':
        if os.system('systemctl is-active ms') == 0:
            os.system('systemctl start ms-save.service')
            await message.channel.send('world saved.')
        else :
            await message.channel.send('Server - CLOSE')

    if message.content == '!status':
        if os.system('systemctl is-active ms') == 0:
            await message.channel.send('Server - OPEN')
        else :
            await message.channel.send('Server - CLOSE')

client.run(TOKEN)

またなんか追加したら記事にしますね。多分追加しない。
不吉なこと言っておくと、2022年の4月だかにdiscord.pyは使えなくなるみたいです。
今は記事を書いているのが1月なので、後3か月の命かも……。
そこらへんは追々、使えなくなったら考えます。
気になる方はjavascriptのdiscord.jsは大丈夫そうなので、そちらで試してみてはどうでしょうか。

DiscordBotを運用するために。

どちらにするかは君次第!可能性は無限大!

前回の記事では、ラズパイの起動と共にサーバーも起動していました。
今回無事DiscordBotを作り上げたので、サーバーの起動設定を変更します。

sudo systemctl disable ms

これで再起動したらラズパイの起動と同時に立ち上がることはなくなりました。
この設定を切らないと、ラズパイの起動と一緒につけやがります。空気読んで。
サブタイトル通りどちらにするかはお好みです。好きな方で使ってください。

次は逆にラズパイの起動と共に、Botを起動するよう設定します。
色々書くのがめんどくさいのでコピーします。

cd /etc/systemd/system
sudo cp ms.service dis.service

中身みたければ前回の記事見てください。
ちょっとだけ変えます。

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

[Service]
Type=forking
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/ms1.18/
ExecStart=/home/ubuntu/ms1.18/distart.sh
Restart=always

[Install]
WantedBy=multi-user.target

DescriptionとExecStartを変更、ExecStopを削除。
シェルもコピーします。

cp start.sh distart.sh

中身はこれ。

#!/bin/sh
screen -UAdmS Discord python3 /home/ubuntu/ms1.18/msdis.py

あとは起動同期設定をして再起動。

sudo systemctl enable dis
sudo reboot

出来ました。
実はここでコマンドに不備が発覚したのはまた別のお話。

ということでセーブ用のms-save.serviceもつくってあげます。

[Unit]
Description=Minecraft Server Save
After=network.target

[Service]
Type=simple
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/ms1.18/
ExecStart=/home/ubuntu/ms1.18/save.sh

[Install]
WantedBy=multi-user.target

save.shは前回作成しました。
これで何とか保存できるようになりました。

時間で保存していたものを消すために、crontabを編集。

0 3 * * * /sbin/reboot
0 12,18 * * * /home/ubuntu/ms1.18/save.sh
↓
0 3 * * * /sbin/reboot

毎日12時の再起動だけ残しておきます。

これでDiscordでコマンド入力するとMinecarft Serverを起動することが、できるようになりました。やったー!!!

いろいろ実験してるやつ


後書き

今回はDiscordでマイクラサーバーを動かせるBotを作成しました。
SSHの奴もできたので、いちいちモニター繋げなくてよくてかなり楽です😊
ただSSHで動かすと、権限が必要なコマンドが増えました。なぜ?
とはいっても再起動とシャットダウンしか確認していませんが。
いうほど面倒でもないので何もしません。

とりあえず形にできてよかった~~!
何故かシェルでscreenに接続することができなくなりましたが、systemctlから動かすことができました。
実装できたはできたけど、何故かうまくいかないのが増えました。なぜ?
結果オーライで済ませていいものか……。いいか!!

また12時間くらいかかってますね。
(内6時間が実装できなかった!sayコマンドですが……😢)
次はドライブにワールドデータ保存するやつやりたいですね。
まあいつになるのやら……。多分3月かな~~??

何はともあれ、今回の記事はここまでです。
おつかれさまでした。自分💣

この記事の続き↓

参考資料

SSHとか英語でかっこつけてんじゃねー!!!

DiscordBotを作っちゃお~~~!

DiscordBotを運用するために。