初めまして
初めまして!さばと言います。
色んなプラットフォームでニュース書いたりブログ書いたり備忘録書いたりしていましたが、Qiitaは初めての投稿です。
なんか気付いたらアドカレ前日当日になってたので、慌てて書いているんですが、本当だったらブラウザからFelicaカードの読み取りをするという内容で投稿しようとしていました。
ちゃんと動くプログラムも作ってあったんはずなんですが、プログラムが何もしてないのに壊れちゃったので、急遽「DiscordのBotを作った話」をしようと思います。
やりたいこと
Discordのサーバー参加者の一覧を出力したいと思ったことがある方は少なくないはず。
名簿と照合したり、ロールを自動で付与したりといった作業をするには、やっぱりCSVファイルの一覧などが欲しくなります。
ですが、Discordの標準機能ではそのようなエクスポート機能がありません。
ということで今回は、Discordのサーバーの参加者一覧を取得し、CSVで出力するBotを作っていきたいと思います。
前提条件
DiscordのBotは誰でも作ることができ、権限があればサーバーに追加することができます。
サーバーに追加するにはDiscord Developer PortalにてBotの登録をし、トークンを入手します。
この辺りを済ませ、すでにトークンを持っている前提で進めます。(初見だと意外に面倒な手順なのですが、説明はサボらせてください...)
どうやって作るの?
Pythonで実装するにあたって、discord.pyという便利なライブラリがあります。
サービス終了するかも?といったニュースがありますが、現時点では使えます。
環境構築
Pythonが実行できる環境で、以下のライブラリをインストールしておきます。
python-dotenvについてはbot作成に必須ではないのですが、トークンを.envファイルに分離しているため、プログラムを動かすのに必要です。
pip install discord.py
pip install python-dotenv
コード
get_member.pyと.envファイルを用意します。
import discord
import os
from dotenv import load_dotenv
class MyClient(discord.Client):
async def on_ready(self):
print(f'Logged on as {self.user}!')
async def on_message(self, message):
print(f'Message from {message.author}: {message.content}')
if message.author == self.user:
return
if message.content.startswith('$hello'): #botの意思疎通確認コマンド
await message.channel.send('Hello!')
elif message.content.startswith('$get_members'): #メンバー一覧を取得してCSVに出力するコマンド
members_list = []
async for member in message.guild.fetch_members():
roles = [role.name for role in member.roles if role.name != "@everyone"]
roles_str = ", ".join(roles) if roles else "None"
members_list.append(f"{member.display_name},{member.id},{roles_str}")
with open('output-files/members.csv', 'w', encoding="utf-8") as file:
file.write('\n'.join(members_list))
await message.channel.send('Saved!!')
else:
print('Command not found.')
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
client = MyClient(intents=intents)
load_dotenv()
client.run(os.environ['TOKEN'])
TOKEN='ここにトークンを書く'
解説
コマンドプロンプトからget_member.pyを実行すると.envに記述したトークンを読み込んでdiscord.pyが動きます。(get_members.pyにハードコーディングしてもいいですが、GitHubなどでコードを管理するときにうっかりお漏らしするのを防ぐため分離しています。GitHubを使うときは.gitignoreに.envファイルを載せておきましょう。)
botが正常に動作すると「Logged on as {Bot名}!」とプロンプトに表示されます。
適当なチャンネルで「$hello」と送信すると、チャンネルにて「Hello!」と帰ってきます。
では、「$get_members」と送信してみましょう。サーバーの参加人数によりますが、数秒してから「Saved!!」と帰ってきます。
これと同時に、get_members.pyがある階層にoutput-filesというディレクトリが作成され、その中にmembers.csvができていればOKです!
出力されるCSVの構造は以下の通りです。
表示名,内部ID,ロール,...
内部IDとは、Discordの内部的に各アカウントに付与されているIDのことで、表示名を変えたとしてもこのIDは不変です。
サーバー参加者のアカウントを識別する場合、この内部IDを使った方が良さそうです。
もし、コマンドを増やしたい場合はon_message関数中にてelifで増やしていきます。
注意点
この記事のBotはコマンドの送信者やコマンドの送信チャンネルを限定していないため、プログラムの実行中は誰かかがどこかのチャンネルでコマンド送信すると実行されてしまいます。
今回の実装では出力結果は自分の手元PCにしか保存されませんが、念のため注意しましょう。