【入門】PythonでMastodonBotを作りたい！【初心者向け】

## 目標
- オウム返しするBotを作る
- mastodon.pyを用いて作るMastodonBotのざっくりとした流れを掴む

## 環境構築
まずはPythonでプログラミングするので**Python**の用意が必要ですね。
あと、MastodonBotを作るためには**mastodon.py**というどこかのスゴい人が用意したAPI[^1]取得のためのライブラリ[^2]が必要です。Pythonのライブラリを簡単にインストールできる**pip**というものを使ってライブラリを用意しましょう。pipは基本的にはPythonをインストールしたら一緒に手に入ります。
Botのコードの中にどのインスタンス[^3]のどのアカウントに書いた挙動を取らせるか判別させるために**アクセストークン**というものを用意する必要があります。
ということで

1-1. **Python**
1-2. **pip**
2. **mastodon.py(ライブラリ)**
3. **アクセストークン**

が必要ですね。順番に用意していきましょう。

### 1-1.Pythonの準備
https://www.python.org/downloads/
このサイトからPythonをダウンロードしてインストールしてください。基本的には最新で、自分の環境のOS用(WindowsやMacなど)の物をダウンロードすれば大丈夫です。
先程インストールしたファイル起動してsetupを行いましょう。`Add Python　3.X.X to PATH`みたいなとこにチェックをしてPATHを通すようにしておきましょう。[^4]そしてInstall Nowを押しましょう。

### 1-2.pipの準備
基本的にPythonに備え付けと思われるので大体の人はこの工程をスルーすることになると思います。pipがきちんと入っているか確認してみましょう。
OSに備え付けのターミナルを起動してください。Windowsで言う「コマンドプロンプト」ですね。Windowsの方は`Win+R`で「ファイルを指定して実行」を起動し`cmd`と打って実行するとコマンドプロンプトを起動できると思います。立ち上げ方がわからない方は各自ググってください。(放棄)
ターミナルで`python -m pip -V`(大文字小文字を間違えないよう注意)と打ち込んでpipのバージョンが出る方は既にpipが入っています。

**もしpipが入っていなかった場合**
以下記事を参考にしてみてください。
https://qiita.com/Chino_Kafuu/items/6be7aa6798c7d7dcc129#もし何かの手違いでpipが入ってなかった場合

### 2.mastodon.pyの準備
ターミナルで`pip install mastodon.py`と打つだけです。pipって便利ですね。

### 3.アクセストークンの準備
Botとして運用したいインスタンスでBotとして運用したいアカウントにログインしてください。何言ってるかわかんない人はとりあえずいつも使ってるMastodonにブラウザでアクセスしてください。
ユーザー設定(歯車のアイコン)を押して、`開発`のタブを押してください。
新規アプリを作るボタンがあるので押してみましょう。アプリ名は好きにしてください。ただしアプリ名は誰でも見れるので注意。保存してもう一度アプリ名を押すとアクセストークンが確認できます。
このアクセストークンを使用することでそのアカウントに好きな挙動を取らせることができます。

## コードを書いてみよう
さてようやくようやくようやくMastodonBotを作る環境が完成しました。
整理しやすいようBot用のフォルダを作り、そこにMastodonBot.pyのようにpythonファイルを作りましょう。
このファイルの中にBotのコードを書いていきます。お好きなテキストエディタ[^5]でこのファイルを開いてください。
まずは以下のコードをコピペしてアクセストークンとURLのところは改変してください。

```python:Bot.py
from mastodon import Mastodon, StreamListener

# Botの主な挙動をここに記述します。
class Bot(StreamListener):
    # Botの準備してくれる所。所謂おまじない。
    def __init__(self):
        super(Bot, self).__init__()
    # アカウントのローカルタイムラインに動きがあると新規トゥートの情報を持って中の挙動を読み取る。
    def on_update(self, status):
        pass

def Login():
    mastodon = Mastodon(
                access_token = "*******************",           # ここにさっき取得したアクセストークンを入れる。
                api_base_url = "https://mastodonexample.com"    # ここにMastodonのインスタンスのURLを記述
                )
    return mastodon

def LTLlisten(mastodon):
    bot = Bot()
    mastodon.stream_local(bot)

# ログインする処理
mastodon = Login()
LTLlisten(mastodon)
```
このコードのon_update関数はLTL(ローカルタイムライン)が動いた時に読み取られます。
そしてLTLに流れた新規トゥートの情報をjsonファイル[^6]としてstatus変数に代入されています。
このコードの中の`pass`の部分を書き換えて書き加えてBotの処理を作っていきます！！

ではまず、ターミナルに新規トゥートの本文を表示させてみましょう。
statusの中にある本文の情報を抜きましょう。`status['content']`と書くと本文の情報が得られます。
それをprint関数で表示してみましょう。

```python:Bot.py
    # アカウントのローカルタイムラインに動きがあると新規トゥートの情報を持って中の挙動を読み取る。
    def on_update(self, status):
        print(status['content'])
```
これをターミナルで実行するとターミナルに本文が出てきます。が、見ていると
`<p>やっはろー</p>`
のようにhtmlの\<p>タグがついています。
pythonには文字列の一部を置換するreplaceというメソッドがあります。それを使って<p>タグを取り除いちゃいましょう。

```python:Bot.py
    # アカウントのローカルタイムラインに動きがあると新規トゥートの情報を持って中の挙動を読み取る。
    def on_update(self, status):
        content = status['content'].replace('<p>', '').replace('</p>', '')
        print(content)
```
このように記述すれば大雑把ですが\<p>タグが消えて本文の見栄えは良くなると思います。
これで本文の情報を抜き出す事ができました。
ではついにオウム返しBotを作りましょう。
Botにトゥートをさせる関数があります。`mastodon.toot()`です。
この()内に文字列を入れるとその文をトゥートします。

```python:Bot.py
    # アカウントのローカルタイムラインに動きがあると新規トゥートの情報を持って中の挙動を読み取る。
    def on_update(self, status):
        mastodon.toot('それは面白い！')     # このまま実行すると迷惑になるのでこれを実行しないでください。
```
ただこのコードだと誰かがトゥートするたびに何かトゥートする鬱陶しいBotになってしまいます。
動く条件を設けて制御してあげましょう。

```python:Bot.py
    # アカウントのローカルタイムラインに動きがあると新規トゥートの情報を持って中の挙動を読み取る。
    def on_update(self, status):
        content = status['content'].replace('<p>', '').replace('</p>', '')
        if '面白い？' in content:
            mastodon.toot('それは面白い！')
```
条件文は文字列`content`の中に`面白い？`が含まれているかどうかという条件になっています。
これで鬱陶しいBotにならなくなりました。
ではさっき取得できるようになった本文をトゥートさせましょう！

```python:Bot.py
    # アカウントのローカルタイムラインに動きがあると新規トゥートの情報を持って中の挙動を読み取る。
    def on_update(self, status):
        content = status['content'].replace('<p>', '').replace('</p>', '')
        if '!Parrot' in content:
            mastodon.toot(content)      # このまま実行すると迷惑になるのでこれを実行しないでください。
```
BotらしくBotが反応する命令っぽいトリガーを用意しました。
ですが、このまま実行すると大変なことになります。(迷惑になりますがやってみるとわかります。)何が起きるのでしょう？
Botが新しくトゥートするとLTLが動くのでもう一度on_update関数を読み取ります。その本文には`!Parrot`が含まれているはずなのでBotのトゥートに対してBotが反応します。
これを繰り返してBotが停止するまで永遠に無限ループを起こします。
これを防ぎましょう。回避方法はいくつかありますが、そのうちの一つの方法を紹介します。

```python:Bot.py
    # アカウントのローカルタイムラインに動きがあると新規トゥートの情報を持って中の挙動を読み取る。
    def on_update(self, status):
        content = status['content'].replace('<p>', '').replace('</p>', '')
        if '!Parrot' in content:
            content = content.replace('!Parrot', '')
            mastodon.toot(content)
```
先程紹介したreplaceメソッドでトリガーとなる部分を除いてあげましょう。
'!Parrot'という文字列を含んだトゥートがLTLに流れるとそれをオウム返しするようになりました。
これでオウム返しBotの完成です！！！

`mastodon.toot()`の他にもBotに様々な挙動を取らせる関数が多数用意されています。
ここのリファレンスを参考に勉強していけば好きなBotが作る事ができるでしょう。
[日本語訳mastodon.pyリファレンス](https://translate.google.com/translate?hl=ja&sl=en&u=https://mastodonpy.readthedocs.io/)

## この記事の参考記事
ご注文はMastodonBotですか？ 今すぐ動かしてみたい初めての方に☕
https://qiita.com/Chino_Kafuu/items/6be7aa6798c7d7dcc129


[^1]: 外部でデータをイジりやすくするためにjson[^6]とかのファイルでデータを返すツール的なやつ
[^2]: python内で便利な色んな関数をまとめたファイルのこと。<br>`import xxx`や`from xxx import yyy, zzz`のように記述すると関数が使える。
[^3]: 一つ一つのMastodonのサーバーのこと。
[^4]: PATHを通すとターミナルでpythonのコマンドを使う時pythonのファイルの場所を書かずに`python`と書くだけで使用できるようになる。よくわかんなかったら便利になる魔法とでも思ってください。
[^5]: プログラミングとかのコードを書くのに使うツール。メモ帳も一応テキストエディタに入るが、VSCode, Vim, Atomなど無料でも便利なテキストエディタがあるので気に入ったものを使ってみよう。ちなみにPythonをダウンロードするとPython用のテキストエディタIDLEが付属して入ってるらしい。
[^6]: データを格納するファイルの記述方法の一つ。webとかでよく見る。