Pythonで自動で返信する機能付きのMastodon botをつくる

#はじめに
Mastodonのbotを作ってみたら意外と簡単だったのでまとめてみます。
使用するライブラリは「Mastodon.py」だけなのであらかじめpipかけておいてください。

#初期設定
まず最初にMastodon側にアプリ登録と認証情報を取得します。これは最初に1回やってしまえば大丈夫なので終わったら消すかコメントアウトしておきましょう。

```python:setup.py

    from mastodon import Mastodon

    url = "imastodon.net"  #使用するインスタンスのアレドレス

    Mastodon.create_app("OtakuCDDB",  #クライアント名、自由に決めましょう
                        api_base_url=url,
                        to_file="cred.txt"
                        )

    mastodon = Mastodon(
        client_id="cred.txt",
        api_base_url=url
    )

    mastodon.log_in(
        "****@*****",  #ログインメールアドレス
        "******",  #パスワード
        to_file="auth.txt"
    )
```

認証情報とcred.txtとauth.txtに保存しましたので次回からはこれを使って認証をします。
ちなみにcred.txtにはクライアントキーとクライアントシークレットがauth.txtにはアクセストークンが保存されてます。

#bot本体
さていよいよbot本体を作っていきましょう。今回はリプライで送られてきた内容を元にAPIを叩いてその結果を返すbotを作っていきます。

```python:bot.py
from mastodon import Mastodon, StreamListener
import requests

class Stream(StreamListener):
    def __init__(self): #継承
        super(Stream, self).__init__()
        # self.logger = logging.getLogger

    def on_notification(self,notif): #通知が来た時に呼び出されます
        if notif['type'] == 'mention': #通知の内容がリプライかチェック
            content = notif['status']['content'] #リプライの本体です
            id = notif['status']['account']['username']
            st = notif['status']
            main(content, st, id)

def main(content,st,id):
    req = content.rsplit(">")[-2].split("<")[0].strip() #リプライの本体から余分な情報を削ります
    r_date = requests.get(url + "?title=" + req, headers="") #apiを叩きます
    print(req)
    try:
        r = r_date.json()["Items"][0] #返ってきたデータを少し加工

        resr = "\n" + "曲名：" + r["Title"] + "\n" + \ #リプライの本体を作っていきます
               "アーティト名：" + r["Artist"] + "\n" + \
               "ボーカル：" + ",".join(r["Vocal"]) + "\n" + \
               "作詞：" + ",".join(r["Word"]) + "\n" + \
               "作曲：" + ",".join(r["Composer"]) + "\n" + \
               "編曲：" + ",".join(r["Arranger"]) + "\n" + \
               "作品：" + ",".join(r["TieUp"]) + "\n" + \
               "ブランド：" + ",".join(r["Brand"]) + "\n" + \
               "ジャンル：" + ",".join(r["Genre"])
    except IndexError: #データが未登録の場合はエラー吐かせて対応します
        resr = "この曲は登録されていません"

    mastodon.status_reply(st,
                          resr,
                          id,
                          visibility='unlisted') #未収載

mastodon = Mastodon(
    client_id = "cred.txt",
    access_token = "auth.txt",
    api_base_url = "https://imastodon.net") #インスタンス

url = "https://********" #APIのURLです

notif = mastodon.notifications() #通知を取得
count = 0

while True:
    if notif[count]['type'] == 'mention':
        if notif[count]['status']['replies_count'] == 0: #リプライが既にされてないのかの確認
            content = notif[count]['status']['content']
            id = notif[count]['status']['account']['username']
            st = notif[count]['status']
            main(content, st, id)
            count += 1
        else:
            break
    else:
        count += 1
    count += 1

mastodon.stream_user(Stream()) #ストリームの起動
```

まず起動時にいままでの通知を取得して返信がなかったらそれに一気に返信をしていきます。
プログラムが落ちてるときに飛んできたリプライに対応したかっただけなのでここら辺はスキップしても大丈夫です。

ストリームを一度起動すると通知が飛んできたらon_notification(self,notif)が呼び出されるのでここに返信機能を盛り込んでおきます。
またリブートやお気に入り等に返信してもしょうがないので通知をリプライか確認します。
リプライだけ取得してくれる都合のいいアレはないみたいです。
あとは適当にまあいろいろ処理してmastodon.status_replyでリプライを飛ばしましょう
以上です。意外と簡単だったんじゃないでしょうか？

#参考文献
[ドキュメント](https://mastodonpy.readthedocs.io/en/stable/)
[Mastodon.py でストリームAPIを使うサンプル](https://gist.github.com/called-d/86f4267caeca34e90a6bcea2527668c8)
[Python逆引きサンプルコード50選（Mastodon API初級編）](https://takulog.info/exercise-python-for-mastodon-1-answer/)
[[Python]Mastodon botを作ってトゥート!してみた!!](https://routecompass.net/mastodon/)