Discord Bot を利用した仮スタンプ機能で暫定毎月7300円おトクにしていく

## はじめに

`Discord`を知らない方に説明すると、`LINE` , `Slack` , `Teams`などのチャット機能に加えてゲーム配信やボイスチャットに特化したアプリとなります。
`Twitter`や`Facebook`といったオープンなSNSと異なりクローズな環境で、ユーザー同士のコミュニケーションを行うことができます。昔で言うところの`Skype`のような遊び・交流に使われています。

## スタンプ機能について

Discordにもスタンプ機能があり、概ねLineのスタンプと同じようにフラットなやり取りが可能です。ただし以下のような制限や違いがあります。
- スタンプは基本的にチャットのグループ(サーバー)に紐づいている
- 無料枠は5まで。サーバー単位で課金(月単位)すると利用可能数が増加する
- LINEのような公式スタンプではなくユーザーがアップロードして登録できる

実際のところDiscordでお気に入りのスタンプを登録しようとしても、ほぼ登録できないので課金する必要があります。
最大60個のスタンプまで登録できるのですが、これを利用する場合は`月額8946円`です(執筆時)。
`サーバーブースト`と呼ばれる課金要素で、スタンプ以外にも様々な特典がありますが、個人的にも所属しているサーバー的にも必要ありませんでした。

スタンプのためにこの値段はさすがに払えない + 誰が払う問題が出てくるので、DiscordのBotを使って疑似的にスタンプを使えるようにしたという話になります。

## 機能動作例

実際に作った機能の前にDiscord標準の機能を確認してみます。

### スタンプ機能(標準)
使い勝手はLineと同様、スタンプを選んで投稿しています。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206583/f981029d-cda2-1048-5751-60b1e24cf052.gif" width="350">

### 絵文字機能(標準)
スタンプとは違いますが似た機能に絵文字があります。
あくまでも絵文字。画像自体が小さいのでスタンプのような表現力はありません。「ヨシ！」の文字も潰れて見えていないのが現状です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206583/10228441-6e16-becf-790c-b2d34e3a8aa3.gif" width="350">


### 仮スタンプ機能
上記の絵文字機能を拡張して実装しました。絵文字の投稿をトリガーとして、BotがWeb上のスタンプサイズの画像を取得して投稿しています。
当然ですが標準スタンプ機能のような即時反映はできません。この挙動とラグを許容できるのであれば全然この機能で問題なくコミュニケーションできるかと思います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3206583/1281d1e7-569a-75e1-33ac-0f2c71f73c74.gif" width="350">

## システムフロー

概ね以下のようなフローでスタンプを表示しています。

```mermaid
sequenceDiagram
  actor User
  User ->> Discord: 絵文字送信
  Bot ->> Discord: 投稿を確認
  Bot ->> Dropbox: 画像検索
  Dropbox ->> Bot: 画像URL送信
  Bot ->> Discord: 投稿ユーザーの絵文字投稿削除
  Bot ->> Discord: 投稿ユーザーと画像URLを紐づけて投稿
```

`Dropbox`に画像を保存している件については前回の記事を参照ください。

https://qiita.com/peko-thunder/items/6c8f0bcd23d1aec994ea

ちなみに投稿者の投稿自体を編集してスタンプ画像を参照する方法はできませんでした。
編集しようとしたらDiscordのApiに怒られます。

> Cannot edit a message authored by another user

他のユーザーのメッセージは編集できません、と。
考えてみたら当然なのですが、他人のメッセージを自由に編集できたらやばいですね。仕方ないので今のようなフローにしています。

## いくらおトクになったか

タイトルの7300円については仮スタンプ機能の登録数やスタンプ無料枠、課金額を元に算出しました。注意点として前述の通りスタンプ機能以外の特典は必要ないので値段を考慮していません。

- 合計60個のスタンプ8946円
- スタンプ機能の登録無料枠5個
- 絵文字機能の登録枠50個

1スタンプ単位の課金額 = 8946 / (60 - 5) = 162.6545...
疑似的に使えるスタンプ数換算の課金額 = 162.6545... * (50 -5) = 7319.45...

## 仮スタンプの利用状況を確認する

現状利用できる仮スタンプは絵文字に登録できる数と同数の50になります。
現在身内で使っているサーバーも既に47個登録されているため、いつか上限に達することになるでしょう。
そうなったら古い使っていないスタンプを削除して入れ替えすることになるかと思うのですが、Discordの機能では使用頻度を調べることができません。

これについては使用履歴をDBに保存する機能を付けました。必要になれば履歴を検索して、使用頻度の低いものを入れ替えれば良いでしょう。

## その他おまけ機能

文字通りおまけ機能です。本筋ではないので省略します。
- 特定時間にスタンプ画像を投稿する
- 朝の時間帯にのみBotが反応してくれる

## 問題点

### Botの稼働時間

どこかしらCloud環境にデプロイすれば24時間365日稼働し続けてくれるのですが、そもそも不要な課金を抑えるために作ったのに、別でコストが出るのは本末転倒と言いますか…
幸いグループのメンバーは夜は普通に寝ている方々なので、Botの稼働を止めても問題ありません。
現在は自宅PCのDocker環境で動かして、夜間はPCをスリープにして、早朝に自動スリープ解除する設定にしてあります。
できればCloud環境で似たようなことをできればと考えています。コスト的にも優先度は高くないので、もしやりたくなったら自腹でやると思います。

### 画像登録

現状DiscordとDropboxの両方でそれぞれ画像を登録する必要があります。
どちらかでの画像登録をトリガーとしてもう片方に登録する、ような作りもできそうではありますが、スタンプ上限などの都合で頻度的には多くありません。
月1 ~ 2で発生する数分のタスクに対して実装をするか？　と考えれば優先度は高くないので未対応です。

## まとめ

ただ課金したくないという課題に対してApiとBotを利用して疑似的に解決してみたという話でした。

さすがにサービス元であるDiscordの課金体系に影響を与える可能性のある本Bot機能を利益化しようとは思いませんが、自分が解決したい課題というのはどこかしら需要があるのかもしれません。機会があればリサーチしてサービス化できればなぁと思うものの、そんなアイデアは早々浮かばないものですね。

今回作成したリポジトリはこちらになります。

https://github.com/peko-thunder/discord-bot