Takuji->find;

株式会社はてなでアプリケーションエンジニアやってます、技術的な記事を書いているつもり

ウマ娘のサークルグループDiscord Botを開発・運用している話

ウマ娘にはオンゲによくあるギルドみたいな「サークル」という機能があって、サークルごとに1ヶ月で育成したウマ娘のファン数合計で競うランキング機能があったり、キャラ強化用のアイテムをサークルメンバーに寄付してショップでアイテム交換できるポイントをもらったり、みたいなことができる。

umamusume.jp

自分が所属しているサークルグループ「ウマ娘愛好会グループ」では創設サークルの「シン・ウマ娘愛好会」や昨年12月からグループに加わったランキング上位サークルの「西京ファーム」を始め3つのサークル最大90人が一つのグループとして活動していて、Discordサーバーを共有している。

3つあるサークルは枠としては別モノだが、毎月サークル間で移籍することができたり、運営は3サークル合同で行ってたりしていて加入手続きやメンバー管理、募集枠の確定などあらゆるプロセスが複雑になりがち。 それを解決するために自前でDiscordのbotとWebUIを開発して運用している。

この記事ではそのシステムの概要について書き連ねることにする。

それぞれの細かい内容は別途記事にする。

サークルの概要

  • 全部でグループサークルは3つ
    • シン・ウマ娘愛好会 (以下 シン)
    • ウマ娘新愛好会:破 (以下 破)
    • 西京ファーム
  • サークルごとに1ヶ月で稼がなければならないファン数が違う、毎月の状況によって月初に西京ファームか「シンまたは破」のどちらかを選ぶことができる
    • シンと破は前月の獲得ファン数に応じて上位30人がシン、残りが破に在籍となるランキング制を採用している
  • 毎月の新規メンバー募集は各サークルに紐付けて行われている
  • 毎月15日辺りから月末までに次月の在籍希望を集計してメンバーを割り振る
    • 毎月全サークル合計で2-3人くらいは脱退or除名者がいる
      • ノルマ未達、引退、更なるステップアップetc.
  • 運営メンバーは専用のプライベートチャンネルで日々の運営業務を行っている
  • 名前はエヴァンゲリオンから来ているが自分は2代目リーダーなので特にエヴァンゲリオンが好き、とかではない

Discordサーバーの概要

  • OBを含めてだいたい120人くらいのメンバーがDiscordにいる、運営メンバーは10人
  • 1人につきDiscordアカウント1つで紐付けされている
  • 日々のコミュニケーションはゲーム内チャットを基本禁止していて、Discordサーバー内のテキストチャンネルやボイスチャンネルで行われる
  • 業務用のSlackなんかによく見られるような話題ごとに細かくチャンネルを分ける運用をしている
    • ウマ娘について雑談するチャンネル
    • 月に1回あるチャンピオンズミーティングというゲーム内の対人イベントに特化した話題を話すチャンネル
    • 愚痴やガチャ結果報告を隔離するチャンネル
    • 個人が自分用に好きにつかっていい個人チャンネル
    • APEXやプリコネなど他のゲームの話題を話すチャンネル
    • etc.
  • ウマ娘に直接関係ない話題や人を選ぶ話題について話されるチャンネルや、個人チャンネルは特定のロールが付与された人のみが読むことができる
  • ボイスチャットを使って雑談したりゲームの配信をすることもある

Discord Botの機能

メンバー一覧

サークルメンバーやOBなどDiscordに加入しているメンバーが一覧できる。

f:id:takuji31:20220412185300p:plain

迅速な移籍のためにトレーナーIDを表示したり、来月のサークルを編集して除名にしたり脱退に変更したりできる。

加入申請

当サークルでは加入のフローをDiscord参加→Webから加入申請→ゲーム内でサークル勧誘→加入に統一している。

これはその加入申請から加入までの状態を管理する機能。

f:id:takuji31:20220412185451p:plain

スクショはバグでBotが加入申請しようとしていることになってるが基本的にはこういう感じ。運営メンバーが各項目にチェックすることで状態が変更される。

  • 勧誘送信済みをチェックするとメンバーにDMで勧誘が送られたことが通知される
  • 加入済みをチェックするとDiscordのロールが「未加入」から各サークルのロールになる

なお、メンバーは以下のような画面でこの申請を行う。

f:id:takuji31:20220412185827p:plain

在籍希望アンケート

ウマ娘ではマンスリーでサークルランキングというサークルメンバーのファン数合計でランキングを競うコンテンツがあって、順位に応じて課金で買えるいわゆる宝石系の通貨とアイテム交換に使えるポイントがもらえる。

そういった特性上どうしてもサークルの加入、脱退が毎月1日に集中するので事前に抜ける人やサークル内での移籍する人が分かっている必要がある。

そのための仕組みとして当サークルでは全メンバー対象の在籍希望アンケートを実施している。

f:id:takuji31:20220412190534p:plain

回答は簡単で毎月中旬くらいに送信される↑のようなメッセージに決まった絵文字でリアクションするだけ。

これにより「自分は来月こういう状況です」というのをメンバーに知らせてもらうことでサークル全体としての状況を把握することができる。

未回答者には期限の4日前から3回、21時に未回答であることがDMでリマインドされる。また、期限前日の21時には全メンバーに回答内容が通知される。

最終的に期限を過ぎても未回答のメンバーは機械的に除名処分にしている。これは「重要な連絡は必ず目を通すように」が守れない人をある程度フィルタリングする目的がある。

メンバーの毎日のファン数記録

当サークルではファン数獲得ノルマがあるため、毎日ゲーム内のスクリーンショットを利用してファン数を集計している。

ファン数を日毎にDBに保存することでランキングを作ったり、直近のファン数獲得の傾向を利用してノルマの見直しをしたりしている。

個人チャンネル開設

個人チャンネルは必要な人だけ作る、という運用にしている。

f:id:takuji31:20220412193042p:plain

こういうメッセージが専用のチャンネルにあって、リアクションするとチャンネルが作られてDMで通知される。

システム構成

共通

  • 言語はTypeScript
  • Prisma + PostgreSQL
  • サーバーはConoHaのVPSにDokkuというプライベートHerokuみたいなPaaSを立ち上げている

www.prisma.io

dokku.com

Bot

  • Botの操作部分はdiscord.js
  • ビルド回りのプロセスを簡略化したいので tsc せずに ts-node --transpile-only で直接動かしている

Web

  • Next.js 12 + React 18
    • 最近はAndroidでもJetpack Composeやってて宣言型じゃないと書くのが(精神的に)つらくなってきた
    • Reactは最近ようやく18にできた
      • Server Components使いたいけど雰囲気をつかめていない
  • CSS書きたくないので全部MUI
  • APIはGraphQL(Nexus) + apollo-server-micro
    • クライアントはurql
  • 基本的には頻繁に変更される情報が多いのでSSGじゃなくSSRしている
  • 認証はNextAuth+Discord

CI/CD周り

  • jestは入れたがテストを書くのをサボっている
  • GitHubのmainにpushしたらDokkuへの自動デプロイ

最後に

今回はひとまずこういうBotを開発してます、くらいの概要の紹介でした。

次回以降の記事でそれぞれの細かい仕組みを紹介していきたい。

おまけ

ウマ娘サークルグループの「ウマ娘愛好会」では、ほぼ毎月20日頃から新規メンバーを募集しています。

Discordがしっかり整理されていてチャンミやチーム競技場に関する情報も充実、毎日賑やかです。

Discord参加OK、チャットでも話せるよって方をお待ちしております。

詳しくは @takuji31 まで。