注意
既にアナウンスされている通り、discord.pyは2021年8月下旬ころ、以降のサポートを停止する旨発表されております。
もし本記事を参考にして不具合が生じた場合、ライブラリのサポート終了による影響である可能性もあります。
詳しくは the_future_of_dpy.md をご覧ください。
概要
チャットツールDiscordにおいてbotを簡潔に記述できる、PythonのDiscordAPIラッパーであるdiscord.py
を利用して、botに定期的な処理を行わせる手法を解説する。
注意
コード例が実際には動作しないものになっておりました。2020年4月10日にコード例を修正しております。
前提
- discord.py 1.3.0a
- Python 3.6
バージョンに関する注意
discord.py
は長らく ver0.16.12
(いわゆるasync版)が提供されてきましたが、2019年4月にv1.0.0(いわゆるrewrite版)がリリースされ、v0系はもはや使用は推奨されていません。
実際、v0系はPython3.7以上には対応しておらず今後のアップデート・メンテナンスは見込めません。
可能な限り、最新版への対応をお勧めします。
v0系での定期的な処理については、以下の記事を参考にしてください。
手法
'discord.py'の拡張であるtasks
を使用します。
これはbot開発でよく用いられる繰り返し実行に主眼を置いたライブラリで、
繰り返し処理を非常に簡潔に記載することができます。
公式のドキュメント
基本的には定期実行を行いたいメソッドの1行上に
@tasks.loop([実行間隔])
を付け加えた上で、定期実行を開始したいタイミングでstart()
するというものです。
次の節で具体的な例を見てみましょう。
具体例
以下は、予め指定したIDを持つチャンネルにbot起動直後から定期実行を10秒ごとに行う例となります。
from discord.ext import tasks
import discord
client = discord.Client()
channel_sent = None
"""
10秒ごとに発言するメソッドを定義している部分。
async def の1行上が定期実行を示すもので、()内で間隔を指定します。
例えば5分ごとなら(minutes=5)です。
"""
@tasks.loop(seconds=10)
async def send_message_every_10sec():
await channel_sent.send("10秒経ったよ")
"""
今回はbotの起動直後に定期実行を開始したいので、
botの準備ができた段階で定期実行をstart()します
"""
@client.event
async def on_ready():
global channel_sent
channel_sent = client.get_channel(any_channel_id)
send_message_every_10sec.start() #定期実行するメソッドの後ろに.start()をつける
client.run("hogehogetoken")
これで、指定したチャンネルに10秒ごとに「10秒経ったよ」と発言させることができます。
応用すれば、指定したコマンドを受け取ったら、そのタイミングから実行することもできます。
start()
のタイミングを変更するだけですね。
終わりに
discord.pyでbotに一定時間ごとに発言させる【async版】
この記事の閲覧数が未だに増え続けていて申し訳なくなったので、ひとまず最新版への動線を作成。必ずアップデートします……。
質問があればコメントください。discord.pyはある程度使いこなせてきました。
コード例の補足
上記のコード例は、いくつかの不具合の報告を受け数回の修正を行ったコードです。もともと記載していたコード例からかけ離れたものにならないよう修正をしているため、少し不自然な部分もあります。
特にglobal
を用いて外側の変数の値を書き換えるのは、必要性がなければ避けるべきです(可読性が落ち、意図せず変数の値を書き換えてしまうこともありえます)。
例えば以下の記事を参考に、ループする関数自体が送信先チャンネルを引数に取るようにすれば、globalで書き換えずともstart()
の引数として渡すだけで済みます。
https://qiita.com/rareshana/items/b84bec58acd48cb14118
あるいは、Cogというコマンドやイベント、タスクをひとまとめにする機能を使えば、インスタンス変数にチャンネルを格納することができるため、やはりglobal変数を使う必要はなくなります。状況に応じて適切に書き換えてください。