mcrconとdiscord.pyを用いてdiscordからminecraftサーバに出力する

<h1>まず初めに</h1>
こちらを読まれていない方は参考にするとより本記事を理解していただけると思います。

https://qiita.com/mutchan1k/items/93fd5450850054fd6122

https://qiita.com/mutchan1k/items/0084af949a9f1dd44e6b

この記事は簡単にまとめたものなので内容は薄いです。

<h1>準備(おさらい)</h1>
まずはdiscord側の準備をしていきましょう。

```ruby:main.py
from discord.ext import commands
import traceback
import discord
cogs = [
    'cogs.cmd'
]

class MyBot(commands.Bot):

    def __init__(self, command_prefix):
        #親クラスにcommand_prefixを渡す
        super().__init__(command_prefix)


        #cogsをひとつずつ読む
        for cog in cogs:
            try:
                self.load_extension(cog)
            except Exception:
                traceback.print_exc()



    # Botの準備完了時に呼び出されるイベント
    async def on_ready(self):
        print('-----')
        print(self.user.name)
        print(self.user.id)
        print('-----')
        await bot.change_presence(activity=discord.Game(f"～～～プレイ中"))



# main.pyのインスタンス化及び起動処理。
if __name__ == '__main__':
    f = open('bot_token.txt', 'r',encoding="utf-8")
    bot = MyBot(command_prefix=commands.when_mentioned_or('')) #command_prefixはコマンドの最初の文字として使うもの。
    bot.run(f.read()) # Botのトークン
```

前回と違うのはトークン保管用のファイルを作ったことですので特に変わりません。

<h1>メインcmd.pyの作成</h1>

:::note warn
cmd.pyのファイルの場所はmain.pyと同じ階層にcogsフォルダーを作りその中に入れてください。

<details><summary>階層略図</summary>

main.py
cogs
 ┗cmd.py
:::

```ruby:cmd.py
from discord.ext import commands
import discord
import subprocess
from mcrcon import MCRcon
import time


server_address = "localhost"
server_pass = "minecraft"
server_port = "25575"


class TestCog(commands.Cog):



    # TestCogクラスのコンストラクタ。Botを受取り、インスタンス変数として保持。
    def __init__(self, bot):
        self.bot = bot
        

    # コマンドの作成。コマンドはcommandデコレータで必ず修飾する。
    @commands.command()
    async def start(self, ctx):
        await ctx.send("起動を開始しました")
        thread1.start()
        subprocess.Popen(r"起動バッチのパス")
        await self.bot.change_presence(status=discord.Status.online,activity=discord.Game(f""))
    
    @commands.command()
    async def stop(self, ctx):
        await ctx.send("サーバを閉じます")
        with MCRcon(server_address, server_pass, server_port) as mcr:
            mcr.command("/stop")
        await self.bot.change_presence(status=discord.Status.idle,activity=discord.Game(f""))
    
    @commands.command()
    async def cm(self, ctx, arg1):
        with MCRcon(server_address, server_pass, server_port) as mcr:
            log = mcr.command(arg1)
        await ctx.send(log)
        

# Bot本体側からコグを読み込む際に呼び出される関数。
def setup(bot):
    bot.add_cog(TestCog(bot))
```

今回新しい要素は`subprocess`でしょうか。
この新しいライブラリを使うことでバッチファイルが起動できるのでディスコードから起動することもできます。

またdiscordのほうで説明だけだった引数の指定も今回は行っています。
> async def cm(self, ctx, arg1)

このように入力することで
```ruby:discordから入力
`command_prefix`cm /stop
```
```ruby:コンソール画面
serverstopping!
```
のようになりdiscord側からコマンドを打てるようになりました。
また今回のは誰でも打ててしまうので`@commands.has_permissions(administrator=True) `をつかって
```ruby:例
@commands.command()
@commands.has_permissions(administrator=True) 
    async def 好きなやつ(self, ctx):
          `好きなプログラム`
```
このようにすると管理者権限を持った人のみ実行できます。

<h1>終わりに</h1>
今回は前回の記事を合わせた内容です。mcrconがわからなければ<a href=https://qiita.com/mutchan1k/items/0084af949a9f1dd44e6b>こちら</a>からdiscordがわからなければ<a href=https://qiita.com/mutchan1k/items/93fd5450850054fd6122>こちら</a>から確認してみてください！



いつも見てくださりありがとうございます。