【discord.py】Among Usのためにランダムに人を選ぶDiscord Botを作りました
現在このbotは公開を停止しています。申し訳ありません。
discord.pyを使ってDiscordのbotを2時間くらいで作った話を書きます。
なんで作ったか
Among Usはクルーメイト(村人)とインポスター(人狼)が争うゲームなのですが、MODを利用して「狂人」「てるてる」などの新役職を入れることができます。
ただし、MODを利用できるのはsteam経由だけなので、iOSやSwitchから参加している人は利用することができません。
そこで、ゲーム内の機能として利用するのではなく、DiscordのDMで通知を送ることでゲーム外で新役職を利用しようと考えました。
仕様
Botの仕様
- Discordのコマンドとして
.darts
コマンドを実装する .darts [channel_name]
でchannel_name
(ボイスチャット)に入っているメンバーからランダムに1人選ぶ- 選ばれた人にDMを送る
デプロイ
実装
Botの用意
Discord Developer PortalからApplicationを作成します。
詳しくはこちらの記事が参考になります(感謝!)
discord.pyでの実装
discord.pyを使います。
discord.Client
を使うパターンと、discord.ext.commands
を使うパターンがあります。
今回のように引数を取るコマンドの場合、discord.ext.commands
を使うのが扱いやすいです。
@bot.command()
デコレータをつけることで、その関数をコマンドとして扱うことができます。
第1引数は commands.Context
が入ってきており、コマンドが叩かれたチャンネルやその文章などの内容が含まれています。
第2引数以降を定義した場合、そのままコマンドの引数になります。
@bot.command() async def darts(ctx: commands.Context, channel_name: str): if ctx.author.bot: return await ctx.message.delete() channel_name = channel_name.lstrip("#") channels = ctx.guild.voice_channels # ボイスチャンネルリストを取得 for ch in channels: if ch.name == channel_name: if not ch.members: await ctx.send(f"#{channel_name}には誰もいません") return member = random.choice(ch.members) await member.send("あなたが選ばれました!") return await ctx.send(f"#{channel_name}が存在しません")
ハマったポイント
ボイスチャットに入っているメンバーを取得するには、Bot側とスクリプト側の両方に設定が必要でした。
Bot側
botの設定ページから SERVER MEMBERS INTENT
をオンにします。
スクリプト側
import discord from discord.ext import commands intents = discord.Intents.default() intents.members = True bot = commands.Bot(command_prefix=".", intents=intents)
コード全体
import os import random import discord from discord.ext import commands from typing import Optional intents = discord.Intents.default() intents.members = True bot = commands.Bot(command_prefix=".", intents=intents) @bot.command() async def darts(ctx: commands.Context, channel_name: str, name: Optional[str] = None): if ctx.author.bot: return await ctx.message.delete() channel_name = channel_name.lstrip("#") channels = ctx.guild.voice_channels for ch in channels: if ch.name == channel_name: if not ch.members: await ctx.send(f"#{channel_name}には誰もいません") return member = random.choice(ch.members) msg = f"{name}に選ばれました!" if name is not None else "あなたが選ばれました!" await member.send(msg) return await ctx.send(f"#{channel_name}が存在しません") TOKEN = os.environ.get("DISCORD_BOT_TOKEN") bot.run(TOKEN)
まとめ
discord.pyは手軽に使えて便利。slack関係のライブラリも見習ってほしい
ソースコードはこちらです