Discord interactions
Discord Developer Portal に文献があります。
APIバージョンはhttps://discord.com/api/v8
です。
前提
すっ飛ばして、ボタンの表示方法知りたい人はボタンの表示を参照。
Botの登録
Discord Dev App へアクセスし、Botを作成してください。そしてTOKEN
を取得しておきましょう。
※方法はネット上に転がっているので省略します。
Python3.8 の構築
本記事ではPython3.8
の環境で行っています。
また、あらかじめライブラリをインストールしておきましょう。
$ python3 -m pip install discord.py
一応、requirements.txtは以下の通りです。
discord~=1.0.1
requests~=2.25.1
aiohttp~=3.7.4.post0
基本的なBotプログラム
import discord
import requests
from discord.ext import commands
from pprint import pprint
import aiohttp
TOKEN = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
AuthB = "Bot " + TOKEN
headers = {
"Authorization": AuthB
}
def returnNormalUrl(channelId):
return "https://discordapp.com/api/channels/" + str(channelId) + "/messages"
async def notify_callback(id, token):
url = "https://discord.com/api/v8/interactions/{0}/{1}/callback".format(id, token)
json = {
"type": 6
}
async with aiohttp.ClientSession() as s:
async with s.post(url, json=json) as r:
if 200 <= r.status < 300:
return
async def on_socket_response(msg):
if msg["t"] != "INTERACTION_CREATE":
return
pprint(msg)
class MyBot(commands.Bot):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add_listener(on_socket_response)
bot = MyBot(command_prefix='$', description='discord bot')
@bot.event
async def on_message(msg):
if msg.content == "hello":
normal_url = returnNormalUrl(msg.channel.id)
json = {
"content": "Hello World"
}
r = requests.post(normal_url, headers=headers, json=json)
bot.run(oTOKEN)
これをコピペしてTOKEN
書き変えて実行すれば多分動きます。(ライブラリ不足のエラー等があればその都度pip
でインストールしてください。Pycharm等のIDEで編集すれば自動的にインストールしてくれるかもしれません。)
アクティビティの表示
@bot.event
async def on_ready():
print("Boot")
await bot.change_presence(activity=discord.Game("Python")) #Pythonをプレイ中
をon_message
関数の前に書けば、
- プログラム起動時にコンソールに
Boot
と表示 - Bot起動中にBotプロフィールに「Pythonをプレイ中」と表示
ボタンメッセージの表示
normal_url = "https://discordapp.com/api/channels/" + str(message.channel.id) + "/messages"
json = {
"content": "Hello World",
"components": [
{
"type": 1,
"components": [
{
"type": 2,
"label": "1st",
"style": 1,
"custom_id": "click_one",
},
{
"type": 2,
"label": "2nd",
"style": 3,
"custom_id": "click_two",
},
]
}
]
}
r = requests.post(normal_url, headers=headers, json=json)
をon_message()
関数内のif
文内に記述等すればボタンが付いたメッセージを表示できます。
"style"
要素では、この文献に書いてあるVALUE
を指定すればよいです。ボタンの色やデザインが変わります。
"custom_id"
の説明はボタン押された時の処理で説明します。
ボタン押された時の処理
on_socket_response
関数の引数となっているmsg
のmsg["d"]["data"]["custom_id"]
にボタンが押された際のcustom_id
が格納されているので、これの値をもとに処理を走らせればよいわけです。
例えばon_socket_response
関数を以下のように変えてみましょう。
async def on_socket_response(msg):
if msg["t"] != "INTERACTION_CREATE":
return
pprint(msg)
custom_id = msg["d"]["data"]["custom_id"]
if custom_id == "click_one":
normal_url = returnNormalUrl(msg["d"]["channel_id"]) #returnNormalUrl関数の定義はこの記事のどこかにあるよ
json = {
"content": "Push button_1"
}
r = requests.post(normal_url, headers=headers, json=json)
await notify_callback(msg["d"]["id"], msg["d"]["token"]) #notify_callback関数は後で説明するよ
こうすると、ボタン1st
が押された際に「Push Button_1」というメッセージが同じチャンネルに投稿されます。
notify_callback
関数の定義
通常、slash commandと同じように、ボタンが押されると「インタラクション」がサーバーに送信されます。このインタラクションに対しサーバーは200
を含んだデータを返さなければなりません。(200
はHTTPステータスコード
の一種で、Successを意味します。)ここで普通にメッセージをインタラクションの成功返信として返してもよいのですが、ボタンが押されるたびにこの返信メッセージが帰ってくるので煩わしいこともあるでしょう。そのため、notify_callback
関数を
async def notify_callback(id, token):
url = "https://discord.com/api/v8/interactions/{0}/{1}/callback".format(id, token)
json = {
"type": 6
}
async with aiohttp.ClientSession() as s:
async with s.post(url, json=json) as r:
if 200 <= r.status < 300:
return
と定義しました。json変数の"type"
で6
を指定しているのはこの文献でもあるようにとりあえず成功返信をするためです。
ボタン押すたびにメッセージを更新
ボタンを押すたびに、ボタンを押せなくしたり、メッセージの番号を+1していく、などしたい時があります。
その際には、更新後のメッセージ内容を格納したjson変数を用意し、
r2 = requests.patch(normal_url2, headers=headers, json=json2)
でPATCH
として送信します。
サンプルコード
左右のボタンを押すたびにメッセージがRightとLeftで切り替わるコードです。ボタンを押すたびに片方のボタンが押せなくなります。
普通にコピペすれば動くはずです....
最後に
間違ってたり、冗長だったらコメントを残していただけると幸いです。
- [2021/5/30 1:21] APIバージョンを追記(コメントありがとうございます。)