どうもmkです。
今回はmastdonのトゥートをDiscordに転送するBotを作る話です。
事の発端
node.jsとかphpとかが話に上がりましたが、Pythonistaの自分としてはPythonで書きたい(それしか書けない)
今回はPythonで書きますが、きっと誰かが他の言語で実装してくれるはず
GAS版 by Tマート店長
偉大なる先駆者であり、今回の発案者
Botの準備
https://discord.com/developers/applications
まずはここにアクセス
![](https://blog.fascode.net/wp-content/uploads/2021/03/image-80.png)
ここを押して
![](https://blog.fascode.net/wp-content/uploads/2021/03/image-81.png)
作るBotの名前を選択
今回は Nerv to Discord にしました
![](https://blog.fascode.net/wp-content/uploads/2021/03/image-82-1024x257.png)
こんな感じの画面に飛ばされるので
Botタブに移動して Add Bot を押す
確認画面が出るので Yes, do it! を選択
写真はお好みで(Save Changes を押すのを忘れずに (1敗))
![](https://blog.fascode.net/wp-content/uploads/2021/03/image-83.png)
アクセストークンをコピー
OAuth2タブに移動して
![](https://blog.fascode.net/wp-content/uploads/2021/03/image-84-1024x281.png)
scopes と書かれたところの bot にチェック
下の方に生成されたURLにアクセス
![](https://blog.fascode.net/wp-content/uploads/2021/03/image-85.png)
追加したいサーバーを選択して 認証 を押す
必要なパッケージのインストール
pip3 install discord
html2text
websockets
今回使うライブラリの用途
discord
ソースコード: https://github.com/Rapptz/discord.py
ドキュメント: https://discordpy.readthedocs.io/ja/latest/index.html
DiscordのAPIとの通信
html2text
ソースコード: https://github.com/aaronsw/html2text
ドキュメント: なし
mastdonのAPIから受け取ったトゥートの内容をmarkdownに変換
websockets
ソースコード: https://github.com/aaugustin/websockets
ドキュメント: https://websockets.readthedocs.io/en/latest/
mastdonのAPIとの通信
mastdonのトゥートを取得
import asyncio
import json
import html2text
import websockets
async def get_toot():
async with websockets.connect("wss://mstdn.jp/api/v1/streaming/?stream=public") as websocket:
while True:
data = json.loads(await websocket.recv())
if data["event"] == "update":
payload = json.loads(data["payload"])
print(html2text.html2text(payload["content"]))
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(get_toot())
今回のテスト用のコードです
Nervだとトゥートがあんまり流れて来ないので今回はmstdn.jpを使用していますあんまりよくないコードだね
解説
正直asyncioよく分かんない
async with websockets.connect("wss://mstdn.jp/api/v1/streaming/?stream=public") as websocket:
websocketに接続
data = json.loads(await websocket.recv())
Pythonのdict型として読み込み
if data["event"] == "update":
update イベントか確認 (delete イベントもある)
payload = json.loads(data["payload"])
最大の謎
何故か data[“payload”] がstr型と認識されるのでdict型に変換
print(html2text.html2text(payload["content"]))
markdownにして表示
Discordに送信
import asyncio
import json
import discord
import html2text
import websockets
TOKEN = "準備編で取得したアクセストークン"
CHANNEL_NAME = "Botが書き込むチャンネル名"
client = discord.Client()
@client.event
async def on_ready():
channel = discord.utils.get(client.get_all_channels(), name=CHANNEL_NAME)
async with websockets.connect("wss://unnerv.jp/api/v1/streaming/?stream=public") as websocket:
while True:
data = json.loads(await websocket.recv())
if data["event"] == "update":
payload = json.loads(data["payload"])
text = html2text.html2text(payload["content"]).splitlines()
images = payload["media_attachments"] if "media_attachments" in payload else None
embed = discord.Embed(title = text[0], description = "\n".join(text[1:]))
if images:
embed.set_image(url=images[0]["preview_url"])
await channel.send(embed = embed)
if len(images) > 1:
for image in images[1:]:
await channel.send(embed = discord.Embed(image = image["preview_url"]))
else:
await channel.send(embed = embed)
if __name__ == "__main__":
client.run(TOKEN)
本番用コードですクソコードとか言わないで
解説
@client.event
async def on_ready():
Botが起動時に実行される
channel = discord.utils.get(client.get_all_channels(), name=CHANNEL_NAME)
チャンネルを検索
text = html2text.html2text(payload["content"]).splitlines()
タイトルと内容を分割
images = payload["media_attachments"] if "media_attachments" in payload else None
トゥートが画像付きなら画像のURLのリストを、そうでなければ None を代入
embed = discord.Embed(title = text[0], description = "\n".join(text[1:]))
Embedを作成
embed.set_image(url=images[0]["preview_url"])
Embedに画像を追加
await channel.send(embed = discord.Embed(image = image["preview_url"]))
画像が複数あったら、画像のみのEmbedを送信
ライブラリを使えば約50行で作れます
やっぱりPythonが最強だね(宗教戦争勃発)
実際に動かしてみた
![](https://blog.fascode.net/wp-content/uploads/2021/03/image-86.png)
使ってみた感想
結構便利で使いやすい
タグとかで絞り込んだり、色分けとかしたらもっと使いやすくなりそう
最後に
豊富なライブラリ、そして簡単に書ける
君もそんなPythonを使ってみないか?遅いとか言わない
インデントがクソだって?
これを使いなさい
次回はFast APIをやるかもしれない
The post MastdonのトゥートをDiscordに転送する話 first appeared on FascodeNetwork Blog.