仕事などでdiscordでミーティングしている時、「予定していた時間を過ぎても参加者が居たらアラート音声を再生するbotとかあったら便利では?」と思ったので、ざっくりと作った過程の覚書。
discord botを作るためのPythonライブラリは何がいいのか調べたが、pycordが良さそうだったのでこれに決定。
決定理由及びpycordの導入については下記の記事を参考にした。
discord bot自体の準備については下記を参考にした。
実装
# timer-bot.py
import asyncio
import sys
import discord
from discord.commands import Option
bot = discord.Bot()
@bot.slash_command(guild_ids=['...']) #コマンドをインストールするサーバーIDを列挙。グローバルコマンドにするには不要。
async def start_timer(
ctx,
minutes: Option(int, 'アラートを上げるまでの時間を入力してください(単位:分)')):
#Optionのメッセージは/start_timerコマンドをdiscordで実行したときに表示される
secondint = int(minutes * 60)
if secondint > 3600:
await ctx.send_response("タイマーは1時間以内にして下さい")
raise BaseException
if secondint >= 0:
await ctx.send_response("タイマーは1分以上の値に設定して下さい")
raise BaseException
message = await ctx.respond(f"Timer: {minutes}")
await asyncio.sleep(secondint)
await ctx.channel.send(content=f"{ctx.author.mention} 終了")
if ctx.channel.type is discord.ChannelType.voice:
vc = await ctx.channel.connect()
try:
if len(ctx.channel.members) == 1:
return
vc.play(discord.FFmpegPCMAudio("alert.mp3")) #任意の音声ファイルを。
while vc.is_playing():
await asyncio.sleep(1)
finally:
await vc.disconnect()
bot.run(sys.argv[1])
実行
python3 timer-bot.py "..." #予め取得してたトークンを渡す
botを落とす場合はPythonのプロセスを落とせばよい。
コマンド実行例
実装していく上で調べた事
- slash commandは
Bot#slash_command
デコレーターを使って実装できる。 - guild_ids未指定だとグローバルコマンドになるが、使用可能になるまで時間がかかるらしいのでサーバーIDを指定して使っている。
- ctxの型はApplicationContext。
ApplicationContext#respond
はslash commandの関数が呼ばれてから3秒以内に呼び出す必要があるようだ。呼び出さなかった場合はアプリケーションの応答なしとしてエラーになる。- slash commandの呼び出し元のチャンネルがボイスチャンネルかどうかは、
ApplicationContext#channel
のtype
属性を見ることで判別できる。 - ffmpegがインストールされているなら、
discord.FFmpegPCMAudio
で音声を簡単に流せる。 VoiceClient#play
はコルーチンではないので、再生中の待機処理は別途記述する必要がある。