Discordで音声チャンネル内のユーザーをランダムで指名するBotを作った
はじめに
こんにちは。ここ2週間ほど週報をサボってしまったんですが、この間はフィヨルドブートキャンプのプラクティスを一時中断しDiscord Botを作っていました。 先週頭に完成し、自分のサーバーとフィヨルドのサーバーに導入してもらい使えるようになったので、bot作りについて軽くまとめてみようかと思います。
もくじ
どんなbotか
Discordの音声チャンネルにミュート解除状態で参加している参加者をランダムで指名するbotです。
コマンド!you
で1人が指名できます。!you 4
のように引数を渡すと引数分の人数が指名できます。
リポジトリは↓
コードの中身
discordrbというgemを使ってRubyで書きました。 最初は単純な条件分岐で書いていたんですが、有識者にリファクタリングしてもらい、今動かしているコードはガード節で書き換えたものになります。
# frozen_string_literal: true require 'dotenv/load' require 'discordrb' bot = Discordrb::Commands::CommandBot.new token: (ENV['TOKEN']).to_s, prefix: '!' bot.command(:you) do |event, number| channel = event.user.voice_channel return event.send_message('ボイスチャンネルに入ってからコマンドを実行してください') if channel.nil? return event.send_message('ミュートを解除してください') if channel.users.all?(&:self_muted?) number = number&.to_i || 1 return event.send_message('選択人数は正の整数を入れてください') unless number > 0 unmuted_users = channel.users.reject(&:self_muted?) user_names = unmuted_users.map(&:name) chosen_users = user_names.sample(number) event.send_message chosen_users.join(", ") end bot.run
最初に作るDiscordrb::Commands::CommandBot
インスタンスがどういう情報を持ってるかが分かると、その後のコードはドキュメントを熟読しなくてもそんなに苦労せずに書けるかなと思います。
私はこのbotを作りはじめて、ようやくbinding.irb
を使ってインスタンスの中身を見ることができるようになってきました…。
なんのために作ったか
毎朝Discord上で輪読会を開催しているのですが、毎回司会1名、ドライバー1名、感想の発表者4人を決めるという作業があります。
bot導入前は、共有のHackMD上の、司会・ドライバー・感想発表を決めるRubyのコードの中に参加者が各々自分の名前を入力してもらい、前回の担当者がターミナルからirbを起動し、コードを実行して決めていました。
具体的に言うと↓を司会、ドライバー、発表者分繰り返す感じ。
irb(main):001:0> %w[hirono yamamori otomo matsunaga makihara].sample => "matsunaga"
この決め方には下記のような問題がありました。
- 毎回書きこむのが面倒
- 絶対誰かが書き忘れる
- 前回のコードをコピペするとその場にいない人も当たる
- 毎回irbを起動するのが面倒
- HackMDの中身がごちゃごちゃする
輪読会が週1くらいの頻度だったら我慢していたのだと思うのですが、平日毎日やっているため、些細なことながらフラストレーションが溜まっていて、なんとかできないかな〜と思ってました。
そんな中、フィヨルドブートキャンプのミートアップにて卒業生のmisosoupさんが、自作サービスでDiscord botを作ったという卒業発表をされているのを聞き、「そうか、Discord上にいる人から選ぶbotを作ればいいのか〜!」と閃き、その翌々日から作り始め大体1週間で完成しました。
大変だったこと
Discord APIの仕様を知ることと、discordrbのドキュメントを読むのがとても大変でした。
さらにdiscordrb人口が少ないため、サンプルコードやStackOverflowでの回答がほとんど見つからなかったのが辛かったです。 あと、スクールのカリキュラム外のことをやっているため、うまく行ってないとき孤独感も強く感じやすいなと思いました。 自分の場合は気持ちが暗くなって何も手につかなくなってしまったため、オンラインカウンセリングを受けたりしてました。受けてすごく気が楽になったので、これから先のプラクティスでも上手に活用していきたいなと思います。
ありがたかったこと
discordrb人口が少なく、抱えている問題を誰に聞けば解決できるのか分からないのが辛かった中、色んな方が手助けしてくれたのがありがたかったです。 特に、Botを公開したその日に、yana_gi (id:yana_g) さんが引数で人数を指定できる機能追加のPR、メンターのu1tnkさんがコード全体のリファクタリングのPRを送ってくださったのがすごく嬉しかったです。
正解は自分で見つけていくしかないんだけど、相手がdiscordrbの専門家かどうかとか、bot作りの経験があるかとか、100%の答えを持っているかどうかに関わらず色んな人に相談してよかったなって思います。
何より毎朝の輪読会で使ってもらえてるのが嬉しく、bot導入前よりずっと便利になったと自分でも思うので、苦労した甲斐があったな〜と思ってます。
これからのこと
このbotの機能拡張案はいろいろ出ていて、人から言われたものをざっとあげると↓のような感じです。
- 指名対象からbotを除外したい
- ただの名前の出力ではなく@でメンションされるようにしたい
- Discordの登録名ではなくニックネームで表示したい
- helpコマンドが欲しい
- 何回も指名したいとき複数回コマンドを打つのが面倒なので絵文字の反応とかでコマンドが実行されるようにしたい
現状なくてめちゃくちゃ困ってる機能というわけではないので、また情熱が戻ってきたらやろうかな〜って感じです。
あとdiscord.pyは国内外で活発な活動をしているようなので、次作りたいbotができたら、Pythonを勉強してdiscord.pyで書いてもいいかなと思ってます。
最後に、Bot作りに関わってくださった方、興味を持ってくださった方、本当にありがとうございました!!
Bot作りで参考にしたURL一覧
公式情報
- Discord Developer Portal — Documentation — Intro
- shardlab/discordrb: Discord API for Ruby
- File: README — Documentation by YARD 0.9.25
Discord bot作りの大体の流れを把握
- DiscordのBotを作ってみよう! | 東京工業大学デジタル創作同好会traP
- イチからDiscord Bot 。for Ruby - Qiita
- 誰でも作れる!Discord Bot(基礎編)|EOi|note
- Ruboty で discord-bot をつくろう
- 簡単なDiscord Botの作り方(初心者向け)|bami|note
- RailsとDiscord APIでサーバーのメンバーを紹介してくれるサービスを作りました | MSSP
GitHub経由でHerokuにデプロイする
秘密情報を環境変数に入れる
- bkeepers/dotenv: A Ruby gem to load environment variables from `.env`.
- object ENV (Ruby 3.0.0 リファレンスマニュアル)
- RubyでTwitterBotを作ろう!【公開編】 | 東京工業大学デジタル創作同好会traP
- 【Rails】 dotenv-railsを使って環境変数を管理しよう | Pikawaka - ピカ1わかりやすいプログラミング用語サイト
- Ruby | dotenv gem で 環境変数をスマートに管理 #ruby #dotenv - Qiita
コマンドで動くbotにする
Heroku上で動かす
- Ruby - discord botをherokuで動かしたい|teratail
- Ruby - HerokuでRubyアプリが開けない(Application Error)|teratail
- Installing libsodium · shardlab/discordrb Wiki