pythonでdiscordを運用するテンプレートcogsの利用

<h1>はじめに</h1>

こちらを参照するとより正確です

https://discordpy.readthedocs.io/ja/latest/intro.html

<h1>インストール</h1>


<details><summary><strong>discord.pyのインストール</strong></summary>

以下のどちらかでインストールします。
```ruby:github
pip install -U discord.py
python -m pip install -U discord.py
```
詳しくは以下を参照
https://discordpy.readthedocs.io/ja/latest/intro.html
</details>
<details><summary><strong>discord-ext-botのインストール</strong></summary>
以下のどちらかでインストールします。

```ruby:github
pip install discord-ext-bot
python -m pip install discord-ext-bot
```

</details>

<h1>botの登録</h1>
以下からdiscord側でbotの作成を行います。

https://discord.com/developers/applications

右上にある
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612850/5794a9b4-bef5-048b-0a9f-0287440ba01a.png)
を押して任意の名前で登録します

登録できたら右にある次のような欄からbotを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612850/c32f3ea9-644f-1bcf-68c8-c5dc187be781.png)
そしてaddbotを押してください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612850/93380174-8325-286c-c9e7-3b13dd4a2a20.png)
私の場合testで作成すると```他のplayerがこの名前を使いすぎているので作成できません```と出たのでなるべくオリジナルの名前にしておくとよいでしょう。

次に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2612850/cb7ea66a-136c-cbda-74fb-ab7ff4b29e31.png)
を押してTOKENを入所しておきましょう。


<h1>準備</h1>

まずはメインファイルにインポート

```ruby:main.py
from discord.ext import commands
import discord
import traceback
```
※tracebackはなくてもよいですが、あると細かいエラーを表示してくれます。

<h3>メインクラスの作成</h3>

```ruby:main.py
class main(commands.Bot):

    def __init__(self, command_prefix):
        # スーパークラスのコンストラクタに値を渡して実行。
        super().__init__(command_prefix)

```
`super().__init__`で親クラス`commands.Bot`に`command_prefix`を渡し実行します。

一番下botが起動するように設定しよう。
```ruby:main.py
if "__main__" == __name__:
    bot = main(command_prefix=commands.when_mentioned_or('任意の文字'))
    bot.run("TOKEN")
```
任意の文字は先頭に記入する文字
`TOKEN`には先ほど手に入れたTOKENをいれる。
<details><summary><strong>if "__main__" == __name__</strong></summary>このファイルが呼ばれたときのみ実行(おまじない)</details>
<details><summary><strong>bot = main(command_prefix=commands.when_mentioned_or('任意の文字'))</strong></summary>
botにメインクラスを代入し、
mainクラスにcommand_prefixの値を代入して実行する。

`commands.when_mentioned_or('任意の文字')`このbotの実行方法である。
メンションもしくは `任意の文字`が打たれた時実行される。
`commands.when_mentioned_or('任意の文字')`のところを丸ごと `"任意の文字"`に変えても実行できる。

</details>
<details><summary><strong>bot.run("TOKEN")</strong></summary>
mainクラスの実行。これでbotが起動する。
</details>

<h4>Botが起動したときコンソールにメッセージを送る</h4>
先ほど作成したメインクラスに次を書き足す

```ruby:main.py main.class
async def on_ready(self):
        print('-----')
        print(self.user.name)
        print(self.user.id)
        print('-----')
        await bot.change_presence(status=discord.Status.online,activity=discord.Game(f"任意の文字"))
```
`async def on_ready(self)`で実行完了時に起動されます。
<details><summary>await bot.change_presence(status=discord.Status.online,activity=discord.Game(f"任意の文字"))</summary>

`status`に`discord.Status.online`や`discord.Status.idle`を代入することでbotを退席中などに編集できる。

`activity=discord.Game(f"任意の文字")`でbotのアクティビティを編集できる。~~建設中をプレイ中~~

</details>




<h1>cogsを作成しよう</h1>
このままメインクラスにつらつらと書くのでもよいがcogsを作成してコマンドごとにファイルを分けよう。

まず初めにmain.pyと同じ階層にcogsフォルダーを作成するその中にcmd.py(好きな名前にしよう)ファイルを作成する。


<h6>次にcogsファイルのcmd.pyを読み込むようにmain.pyを書き換える</h6>
まずは読み込むファイルリストをインポートの下に書く。

```ruby:main.py
cogslist=[
   'cogs.cmd'
]
```

次にメインクラスにてcogslistを読み込むようにする。
```ruby:main.py main.class
for cog in cogslist:
    try:
       self.load_extension(cog)
    except Exception:
       traceback.print_exc()
```
:::note warn
注意
<a>準備</a>でtracebackを入れてない方は`traceback.print_exc()`を`pass`に書き換えよう。
:::

`try`コマンドでエラーをはじき出しbotの実行を優先します。
<details><summary>self.load_extension(cog)</summary>

`for ~ in ~`でcogに代入されたcogslistにあるファイルを一つずつ読み込みます。
</details>

<h3>cmd.pyをかこう</h3>
cmdにもクラスを作成、インポートもする。

```ruby:cmd.py
from discord.ext import commands
import discord

class TestCog(commands.Cog):

    def __init__(self, bot):
        self.bot = bot

def setup(bot):
    bot.add_cog(TestCog(bot))
```
<details><summary>def __init__(self, bot):
        self.bot = bot</summary>
main.pyからもらったbot変数をself.botに代入してインスタンス変数(class内で使える変数)にする。

</details>
<details><summary>def setup(bot):
    bot.add_cog(TestCog(bot))</summary>
main.pyはsetup関数を覗きに来るのでここにclassを読み込むように指定する。
</details>
あとはクラス内に次のように記入をすればコマンドを作成できる。

```ruby:cmd.py TestCog.class
@commands.command()
    async def test(self, ctx):
        await ctx.send("テスト成功！")
```
:::note warn
注意
毎回`@commands.command()`で関数はデコレータしてください。
:::
<details><summary>async def test(self,ctx)</summary>
この関数でコマンドを指定しています。
main.pyで指定したcommand_prefixの後にtestと入力するとこの関数が実行されます。
またこの関数の引数を増やすことでtestの後ろに半角スペース開けて入力された値を利用することもできます。
</details>

<h1>終わりに</h1>
今回はcogについての話を重点的に話しました。
コマンドの作成以外にもたくさんの機能があるのでdiscord.pyについては良く調べねば、、、
私もよくわからないことが多いのでこれから研究ですね。




<h1>参考</h1>

https://discordpy.readthedocs.io/ja/latest/intro.html